Лучший способ обновить Django-модель-экземпляр/таблицу базы данных с другого сервера без Django

#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? Я имею в виду, что, поскольку я могу управлять многими моделями через этот интерфейс, а не только «Книгой», нецелесообразно явно объявлять все возможные модели.