Django Rest Framework admin extend model - python

I am trying to extend Django admin model.
This is the code that I have:
from django.contrib import admin
from .models import *
from markdownx.admin import MarkdownxModelAdmin
def process_topics(_, __, queryset):
from person.tasks import calculate_factors
for object in queryset:
calculate_factors(object)
process_topics.short_description = "Process topics manually"
class ObjectAdmin(admin.ModelAdmin):
list_display = ('pk', 'sender', 'note',)
actions = [process_topics, ]
# admin.site.register(Object, ObjectAdmin)
admin.site.register(Object, MarkdownxModelAdmin)
I would like to use ObjectAdmin to extend MarkdownxModelAdmin class.

Posting as an answer, since there is no accepted answer yet :)
class ObjectAdmin(MarkdownxModelAdmin): ... Should do it.

Related

Why using validators=[URLValidator] when defining a model CharField doesn't make it check for URL-validity upon saving the corresponding ModelForm?

app.models.py:
from django.core.validators import URLValidator
from django.db import models
class Snapshot(models.Model):
url = models.CharField(max_length=1999, validators=[URLValidator])
app.forms.py:
from django import forms
from .models import Snapshot
class SnapshotForm(forms.ModelForm):
class Meta:
model = Snapshot
fields = ('url',)
app.views.py:
from django.http import HttpResponse
from .forms import SnapshotForm
def index(request):
snapshot_form = SnapshotForm(data={'url': 'not an URL!'})
if snapshot_form.is_valid():
snapshot_form.save()
return HttpResponse("")
Why does it save 'not an URL!' into DB, despite the fact that it ain't a valid URL?!
What is the right way to incorporate URLValidator?
You've specified the validators for your field like so: validators=[URLValidator]. This is incorrect because the validators argument takes in a list of callables that perform the validation. In this case even though URLValidator is callable but that's actually the __init__ method of the class being called. You need to pass an instance of the class for it to work properly:
# Note the brackets after URLValidator to instantiate the class
url = models.CharField(max_length=1999, validators=[URLValidator()])
Better yet since you want to take input a URL you should simply use the URLField class for your field:
url = models.URLField(max_length=1999)

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 How to show a customized admin model

Hi I want to show a customized admin model in the admin section of Django
So far I created a test_data class like this
class TestData:
#classmethod
def get_test_data(self):
list = []
for x in range(0,50):
list.append(x)
return list
and I import it on to the admin.py
from django.contrib import admin
from polls.test_data import TestData
class TestClass(admin.ModelAdmin):
list = TestData.get_test_data()
admin. site.register(TestClass)
and this gives me an error
TypeError: 'MediaDefiningClass' object is not iterable
How to fix this and show custom model in admin ? Thank you in advance
You can't pass a ModelAdmin object as the first argument to admin.site.register()
try
admin.site.register(TestData, TestClass)
You'll also need to tell your TestClass what model it refers to. more info here.

Django add field to existing model app

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)

Testing with a custom user model as a ForeignKey in Django 1.5

I'm using Django 1.5 and I'm trying to make an application work with any custom user model. I've changed the app to use get_user_model everywhere and the app itself is not showing any problems so far.
The issue is that I want to be able to test the app as well, but I can't find a way to make ForeignKey model fields to test correctly using custom user models. When I run the test case attached below, I get this error:
ValueError: Cannot assign "<NewCustomUser: alice#bob.net>": "ModelWithForeign.user" must be a "User" instance.
This is the file I'm using for testing:
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.tests.custom_user import CustomUser, CustomUserManager
from django.db import models
from django.test import TestCase
from django.test.utils import override_settings
class NewCustomUser(CustomUser):
objects = CustomUserManager()
class Meta:
app_label = 'myapp'
class ModelWithForeign(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
#override_settings(
AUTH_USER_MODEL = 'myapp.NewCustomUser'
)
class MyTest(TestCase):
user_info = {
'email': 'alice#bob.net',
'date_of_birth': '2013-03-12',
'password': 'password1'
}
def test_failing(self):
u = get_user_model()(**self.user_info)
m = ModelWithForeign(user=u)
m.save()
I'm referencing the user model in the ForeignKey argument list as described here, but using get_user_model there doesn't change anything, as the user attribute is evaluated before the setting change takes place. Is there a way to make this ForeignKey play nice with testing when I'm using custom user models?
I asked about this on the Django mailing list as well but it seems that, at least currently, there is no way to change the settings.AUTH_USER_MODEL and have it work nicely with a ForeignKey.
So far, in order to test my app, I've created a runtests.py file from this answer:
import os, sys
from django.conf import settings
if len(sys.argv) >= 2:
user_model = sys.argv[1]
else:
user_model = 'auth.User'
settings.configure(
...
AUTH_USER_MODEL=user_model,
...
)
...
And added a bash script to actually run the tests using different user models:
for i in "auth.User" "myapp.NewCustomUser"; do
echo "Running with AUTH_USER_MODEL=$i"
python runtests.py $i
if [ $? -ne 0 ]; then
break
fi
done
The last bit is to use a function to actually retrieve the right user model info instead of just using a "static" variable:
def get_user_info():
if settings.AUTH_USER_MODEL == 'auth.User':
return {default user info}
if settings.AUTH_USER_MODEL == 'myapp.NewCustomUser':
return {my custom user info}
raise NotImplementedError
I'm not claiming this to be a correct answer for the problem, but so far... It works.

Categories