#python #django
Вопрос:
Допустим, у меня есть два сервера prod
и API
.
На prod
мне запущено приложение Django, и я говорю, что у меня есть следующая модель
class MyModel(model.Models):
name = models.Charfield()
age = models.IntField()
birthdate = models.DateTimeField()
has_birthday = models.BooleanField()
таким образом, модель в моей базе данных будет выглядеть так
name | age | birthdate | has_birthday
----- ------- ------------- -------------
john 30 1990-01-30 0
doe 20 1987-05-01 0
....
Каждый день API
я запускаю ежедневный скрипт, который проверяет, есть ли у кого — то день рождения-если есть, установите has_birthday=1
(обратите внимание, все вышеизложенное-просто пример для иллюстрации).
Поскольку API
just является сервером для ежедневных заданий, я не развернул приложение Django на этом сервере, поэтому мне интересно, каков обычный/лучший способ обновить MyModel
таблицу со следующей логикой?
Моя первая интуиция заключается в том, чтобы просто сделать простое и update
понятное заявление, например, на языке SQL
from utils import get_con_to_db
con = get_con_to_db()
query = <SQL update query>
con.execute(query)
но это довольно подвержено ошибкам, если я решу каким-то образом изменить свою модель. Существует ли лучший/более безопасный способ сделать это без необходимости создавать приложение Django API
, поддерживая таким образом два приложения Django?
Ответ №1:
Вы можете определить URL-адрес с включенной функцией просмотра do_orm_operation
prod server
, затем вы можете выполнить операцию ORM API server
, отправив запрос POST на URL-адрес, его конкретная реализация выглядит следующим образом(основная идея заключается в использовании eval,):
from django.shortcuts import HttpResponse
import django
# Create your views here.
models = django.apps.apps.get_models()
models_names = {mod.__name__: mod for mod in models}
def do_orm_operation(request):
"""
This method supports CURD, you just need to send a request by `POST` method,
the post data should be the format `{'model': 'your_model_name', 'cmd': 'your_orm_operation_begins_with_objects'}`,
Eg: requests.post(data={'model': 'Book', 'cmd': 'objects.filter(name='book1').update(name="mybook")'}, url='http://127.0.0.1:8000/do_orm_operation/')
"""
try:
data = request.POST
model_name = data['model']
cmd = data['cmd']
model = models_names[model_name] # this variable will be used in eval
query = 'model.' cmd
res = eval(query)
print('res:', res)
# then do whatever you want
return HttpResponse('success')
except:
return HttpResponse('error')
Примечание. При использовании этого метода необходимо обратить внимание на проблемы безопасности, чтобы предотвратить вредоносное выполнение операций с базой данных.
Комментарии:
1. Похоже, это действительно хороший способ сделать это! Мне нужно будет настроить некоторые учетные данные для
API
, хотя, я полагаю2. В чем идея наличия
model
иcmd
, а не толькоcmd = 'Book.objects.filter(name="book1").update(name="new name")'
и тогдаeval(cmd)
?3. Когда мы используем
eval('Book.objects....")')
,eval
будет искать переменную «Книга», но мы не можем явно объявить ее перед выполнениемeval
, потому что мы можем использовать другие модели, такие как » Человек.объекты….».4. Я заставил это работать, просто отправив a
cmd
иeval
это, напримерeval(Book.objects.filter(name="book1").update(name="new name"))
5. Вы сделали это, сначала объявив переменную Book? Я имею в виду, что, поскольку я могу управлять многими моделями через этот интерфейс, а не только «Книгой», нецелесообразно явно объявлять все возможные модели.