Django add field to existing model app - python

in my new Django app I use 3rd-part Photologue app.
This app works well, but I need to add some field in its model without change the original source code of Photologue app.
With this snippet, all works well, but maybe this is not the best solution:
Photo.add_to_class("link", models.URLField(max_leng.... ))
I've read some posts where I should use OneToOneRelationField ... but then, in django admin app, I will have two different form page of Photo and new PhotoLink class...
Does anyone can help me?

If you are using a OneToOneField, you can use your 'extension' model as an inline to the model you are extending. You do this by first un-registering the original admin class, and then overriding it with our variant:
from otherapp.admin import OriginalFooAdmin
from otherapp.models import Foo
from yourapp.models import YourExtension
from django.contrib import admin
admin.site.unregister(Foo)
class ExtensionInline(admin.StackedInline):
model = YourExtension
class NewFooAdmin(OriginalFooAdmin):
inlines = OriginalFooAdmin.inlines + [ExtensionInline]
admin.site.register(Foo, NewFooAdmin)

Related

in python , How to load just one time a ML model in a rest service like django or flask?

I have a ML model saved in a pkl (pickel file), I have no problem loading this model and using it for prediction, even I have a rest service that expose it, the only problem is that I load the model in every request, something like this:
https://www.analyticsvidhya.com/blog/2017/09/machine-learning-models-as-apis-using-flask/
I really want that my model just load one time like a global variable and every request useing this variable without the necessity of load the model every request
is it possible?
You can assign the model variable in settings.py. Whenever the server will start/restart django will store the model variable globally. It can be accessed like
from django.conf import settings
print settings.my_ml_model_variable
Based on the comment of Kaushal, I solved my problem using django rest framework as the following:
first I saved my model as :
> joblib.dump(<your scikit model here> , <"yourfilename.pkl">, compress
> = 1)
Once I had my model saved with the pkl extension I needed to create a variable in the settings.py file(this file is created automatically by django)
YOURMODEL = joblib.load(<"yourfilename.pkl">)
The django process call this file when you start your server, so it is called just one time
Now we just need to call our model in whatever place we want, usually in a views.py file since we are using django and/or django-rest-framework
myModel = getattr(settings, 'YOURMODEL', 'the_default_value')
res = myModel.predict_proba(s).tolist()
A simple example of the rest service:
from django.conf import settings
class myClass(APIView):
permission_classes = (permissions.AllowAny,)
'''Httpverb post method'''
def post(self, request,format=None):
myModel = getattr(settings, '../mymodel.pkl', 'the_default_value')
data = preparePostData(request.data)
res = myModel.predict_proba(data).tolist()
message = prepareMessage(res)
return Response(message, status=status.HTTP_200_OK)
Here preparePostData and prepareMessage are just function that I developed for prepare the object to my model and my response
Regards
You can do it in Django by creating yourfile.py config.
Just you should redfine the django AppConfig there, and instanciate your models .
It will load all your models when django is starting for just once .
After that you can use it in views simpely by importing your class models from yourfile.py .
To do that you should define Yourfile.py
It should look like that :
from django.apps import AppConfig
class YourModelsConfig(AppConfig):
#write what you need
And in your views you can do:
from yourfile import YourModelsConfig
YourModelsConfig.your_method_or_your_variable
I think you can get more details here .
https://medium.com/saarthi-ai/deploying-a-machine-learning-model-using-django-part-1-6c7de05c8d7v

Expose a Django app's models at the module level

I've made a django app, which is designed to be easily pluggable, and only has 1 view, and 1 model that project planning to use the app need to be aware of.
For ease, I'd like to just make the view and model available from the app-level. So rather than:
from mything.views import MyView
from mything.models import MyModel
You can instead just do:
from mything import MyView, MyModel
I changed the __init__.py file in the app to be like this:
from .views import MyView
from .models import MyModel
Of course I get the old django.core.exceptions.AppRegistryNotReady raised, since it's attempting to run the models.py code before the apps are loaded.
So I came up with the following workaround, and I'm wondering if it's a reasonable pattern to use or not. Now in __init__.py I have:
def _expose_items():
from .views import MyView
from .models import MyModel
globals()['MyView'] = MyView
globals()['MyModel'] = MyModel
And in my app's apps.py:
from . import _expose_items
class MyThingConfig(AppConfig):
name = 'mything'
def ready(self):
_expose_items()
So now indeed, I can directly import the view and model from the outside. Is this useful, or horrible?
Most Django apps do not collect views or models to the top level module. Refer to django.contrib.auth as an example.
Most Django apps do not collect views or models to the top level module. Use clear documentation to demonstrate how to import from your app. Hacks including globals() will probably create more trouble than help.
Refer to django.contrib.auth as an example.

OpenLayersWidget & Django Admin Maps over Https

I'm still a novice Django/Python user, so apologies for the basic question.
I'm running into a problem where maps are not showing up in my Django admin. I was hoping to fix this problem by adding the OpenLayersWidget class to my forms.py project file, referenced in the Django docs here: https://docs.djangoproject.com/en/1.9/ref/contrib/gis/forms-api/#django.contrib.gis.widgets.OpenLayersWidget. See below.
from django import forms
from django.contrib.gis.admin.widgets import OpenLayersWidget
class OpenLayersWidget(forms.TextInput):
"""Specifying CDN of openlayers.js in the Media class."""
class Media:
js = (
'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1',
)
I'm sure this is too simplistic.
Unfortunately, the above does not work over https. Any ideas?
Try this:
from django.contrib.gis import admin as gis_admin
class SecureOSM(gis_admin.OSMGeoAdmin):
openlayers_url = 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js'
Then inherit from here
Update
The https cloudflare url has become the default as of Django 1.11. So patching should not be necessary anymore.
You need override the forms Widget. Example:
from django.contrib import admin
from django.contrib.gis.db import models
from django.contrib.gis.forms.widgets import BaseGeometryWidget
class CustomOpenLayersWidget(BaseGeometryWidget):
template_name = 'gis/openlayers.html'
def __init__(self, attrs=None):
super(CustomOpenLayersWidget, self).__init__(attrs)
class Media:
js = (
'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js',
'gis/js/OLMapWidget.js',
)
class CustomModelAdmin(admin.ModelAdmin):
"""Need to change default URL of OpenLayers"""
formfield_overrides = {
models.PointField: {"widget": CustomOpenLayersWidget},
models.PointField: {"widget": CustomOpenLayersWidget},
models.PolygonField: {"widget": CustomOpenLayersWidget},
models.LineStringField: {"widget": CustomOpenLayersWidget},
# Adding other models Fields if need
}
and change the admin class
#admin.register(Position)
class PositionAdmin(CustomModelAdmin):
pass
A example of model
class Position(models.Model):
point = models.PointField(blank=False)
The code override field forms widgets to a new media itens. This remove http content http://openlayers.org/api/2.13.1/OpenLayers.js of media.

django AdminSite instance delete error in model

I created an instance of AdminSite as I wanted the admin page for editing the models available under my app (as opposed to the project):
in the myproj/myapp/admins.py I have:
from django.contrib.admin.sites import AdminSite
from models import mymodel
class myadminsite(AdminSite):
pass
my_admin_site = myadminsite(AdminSite)
my_admin_site.register(my model)
in the myproj/myapp/urls.py I have :
url(r'admin/', include(my_admin_site.urls)),
So when I point my browser to 'http://example.com/myapp/admin' I get the admin page correctly and when I log in I see the model also. I am able to add and modify any of the model objects without any problem. BUT when I try to delete any of the model objects it gives me this error:
NoReverseMatch at /myapp/admin/myapp/mymodel/2/delete/
u"<class 'django.contrib.admin.sites.AdminSite'>" is not a registered namespace
I have been trying for almost four hours now to figure out what is wrong but am unable to. Any ideas/help will be very much appreciated.

ReferenceField in mongoengine

I use mongoengine with django. I have two applications with models.
app1/models.py:
from mongoengine import fields
from mongoengine.document import Document
class Model1(Document):
name = fields.StringField()
lists = fields.ListField(fields.ReferenceField("Model2", dbref=False))
app2/models.py:
from mongoengine import fields
from mongoengine.document import Document
class Model2(Document):
name = fields.StringField()
All applications were added to INSTALLED_APPS. When I use the django dev-server, everything is fine. But using this code with uwsgi-server there is an error:
Model2 has not been registered in the document registry.
Importing the document class automatically registers it, has it
been imported?
What I should do?
You should import app2.models somewhere. Put a comment by the import saying why it's there, so nobody removes the useless-looking import in the future.
When the django dev server starts up it imports the models from all installed apps and validates them. You'll see
Validating models...
0 errors found
This does not happen in a production environment. It is just a nicety of the dev server.

Categories