I have a ReactJS table that uses fetch API to get the data from a Django server using Rest. I've defined the viewset to use OrderingFilter and specified the ordering_fields as so:
class RecipientViewSet(BaseViewSetClass):
permission_classes = (IsAuthenticated,)
serializer_class = serializers.RecipientsSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = (
'id',
'externalID',
'firstname',
'lastname',
)
It works great, but I want to know if there's a method of getting from the ordering_fields from the server with fetch, so that I can add a sort icon only for the table headers that can be used to set the data's ordering.
I should add that in the Django REST Framework GUI I can click "Filters" button and view all possible filters for this viewset, and that's exactly what I want to get with ReactJS.
Thanks for any help!
I don't think there is a way to get the ordering fields out of the box via an API call, but you can always add an endpoint to return them:
from rest_framework import viewsets
from rest_framework.decorators import list_route
class MyViewSet(viewsets.GenericViewSet):
ordering_fields = ('a', 'b')
#list_route
def get_ordering_fields(self, request):
return self.ordering_fields
This way calling /your_endpoint/get_ordering_fields/ will return the list of ordering fields defined in the class. You can apply any formatting before returning them if you wish.
Also keep in mind that this behavior can be implemented in a base or mixin class so it can be reused easily later.
See the docs about list and detail routes.
I'm using django 1.11 and I tried to to create django dynamic models by referring this link https://code.djangoproject.com/wiki/DynamicModels , by executing each and every step it runs without any issue, but How can I see this created table in django admin panel?
action.py
from django.db import models
from django.contrib import admin
def create_model(name, fields=None, app_label='', module='', options=None, admin_opts=None):
"""
Create specified model
"""
class Meta:
# Using type('Meta', ...) gives a dictproxy error during model creation
pass
if app_label:
# app_label must be set using the Meta inner class
setattr(Meta, 'app_label', app_label)
# Update Meta with any options that were provided
if options is not None:
for key, value in options.iteritems():
setattr(Meta, key, value)
# Set up a dictionary to simulate declarations within a class
attrs = {'__module__': module, 'Meta': Meta}
# Add in any fields that were provided
if fields:
attrs.update(fields)
# Create the class, which automatically triggers ModelBase processing
model = type(name, (models.Model,), attrs)
# Create an Admin class if admin options were provided
if admin_opts is not None:
print admin_opts
class Admin(admin.ModelAdmin):
pass
for key, value in admin_opts:
setattr(Admin, key, value)
admin.site.register(model, Admin)
return model
In Console:
from action import create_model
from django.db import models
fields = {
'first_name': models.CharField(max_length=255),
'last_name': models.CharField(max_length=255),
'__str__': lambda self: '%s %s' (self.first_name, self.last_name),
}
options = {
'ordering': ['last_name', 'first_name'],
'verbose_name': 'valued customer',
}
admin_opts = {}
model = create_model('Person', fields,
options=options,
admin_opts=admin_opts,
app_label='form',
module='project.app.model',
)
I can see no. of fields by
len(model._meta.fields)
But I have no idea of, how to register the created model in admin, and what parameter will come inside admin_opts = {} , how can i do makemigrations and migrate,how can I access this model in views.py, from where i will import this model .Can you guys please help me for this , it will be very useful for me and Thanks in advance.
with connection.schema_editor() as editor:
editor.create_model(Model)
This is from github source code , try it instead of sql_model_create and I try to success in my project,and it's true..
I have worked hard for a long time because I don't find django-dynamic-model in "django 1.10".
I think you forgot to execute this function.
def install(model):
from django.core.management import sql, color
from django.db import connection
# Standard syncdb expects models to be in reliable locations,
# so dynamic models need to bypass django.core.management.syncdb.
# On the plus side, this allows individual models to be installed
# without installing the entire project structure.
# On the other hand, this means that things like relationships and
# indexes will have to be handled manually.
# This installs only the basic table definition.
# disable terminal colors in the sql statements
style = color.no_style()
cursor = connection.cursor()
statements, pending = sql.sql_model_create(model, style)
for sql in statements:
cursor.execute(sql)
I'm implementing a user filter system on a website. Users are to be able to select 'categories' and 'packages' of interest to them and have the matching data presented when they log in. Both sets of data will come from HTML select forms eg. Categories: 'null pointers', 'dead code'... and packages 'package_x', 'package_y', 'package_z'...
My question is about the best way to store this list information in a database (I am using Django and PostgresSQL).
My initial thought is to have a table like this:
user_id - one to one field
categories - textfield - store json data
packages - textfield - store json data
Is there a better way to be doing this?
I would go the route of using a user profile with categories and packages being many to many fields.
In models.py
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=255)
class Package(models.Model):
name = models.CharField(max_length=255)
class UserProfile(models.Model):
user = models.ForiegnKey(User)
categories = models.ManyToManyField(Category)
packages = models.ManyToManyField(Package)
In admin.py
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class CustomUserAdmin(UserAdmin):
inlines = [UserProfile]
#filter_horizontal = ('',) #Makes the selection a bit more friendly
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
In views.py
user_with_profile = User.objects.get(pk=user_id).get_profile()
All that being said. Django 1.5 will replace the user profile with being able to use a configurable user model.
I have a Django-tastypie resource that represents a banner and has a field called impression that I increment whenever the banner appears on the site.
class BannerResource(ModelResource):
owner = fields.ForeignKey('advertisment.api.AdvertiserResource', 'owner', full=True)
class Meta:
queryset = Banner.objects.all()
resource_name = 'banner'
authorization = Authorization()
I would like to get the banner that has the minimum impression, in the official documentation there is nothing like
filtering = {'impressions': ('min',)}
I'm using BackboneJS in the front end and I could get all the banners with Backbone collection and do the filtering with JavaScript but I'm looking for a quicker way to do it.
Any ideas?
Thanks
If you'd like to retrieve banners with number of impressions greater than X you need to things. For one you need to define possible filtering operations on your resource like so (given your model has impressions field):
class BannerResource(ModelResource):
owner = fields.ForeignKey('advertisment.api.AdvertiserResource', 'owner', full=True)
class Meta:
queryset = Banner.objects.all()
resource_name = 'banner'
authorization = Authorization()
filtering = { 'impressions' : ALL }
for available options take a look at Tastypie's documentation on filtering.
Then if you made the following request:
GET http://<your_host>/v1/banners?impressions__gte=X
you should get what you need.
here is the models page
In this picture, only the title shows up on here, I used:
def __unicode__(self):
return self.title;
here is the each individual objects
How do I show all these fields?
How do I show all the fields in each Model page?
If you want to include all fields without typing all fieldnames, you can use
list_display = BookAdmin._meta.get_all_field_names()
The drawback is, the fields are in sorted order.
Edit:
This method has been deprecated in Django 1.10 See Migrating from old API for reference. Following should work instead for Django >= 1.9 for most cases -
list_display = [field.name for field in Book._meta.get_fields()]
By default, the admin layout only shows what is returned from the object's unicode function. To display something else you need to create a custom admin form in app_dir/admin.py.
See here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
You need to add an admin form, and setting the list_display field.
In your specific example (admin.py):
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'price')
admin.site.register(Book, BookAdmin)
If you want to include all but the ManyToManyField field names, and have them in the same order as in the models.py file, you can use:
list_display = [field.name for field in Book._meta.fields if field.name != "id"]
As you can see, I also excluded the id.
If you find yourself doing this a lot, you could create a subclass of ModelAdmin:
class CustomModelAdmin(admin.ModelAdmin):
def __init__(self, model, admin_site):
self.list_display = [field.name for field in model._meta.fields if field.name != "id"]
super(CustomModelAdmin, self).__init__(model, admin_site)
and then just inherit from that:
class BookAdmin(CustomModelAdmin):
pass
or you can do it as a mixin:
class CustomModelAdminMixin(object):
def __init__(self, model, admin_site):
self.list_display = [field.name for field in model._meta.fields if field.name != "id"]
super(CustomModelAdminMixin, self).__init__(model, admin_site)
class TradeAdmin(CustomModelAdminMixin, admin.ModelAdmin):
pass
The mixin is useful if you want to inherit from something other than admin.ModelAdmin.
I found OBu's answer here to be very useful for me. He mentions:
The drawback is, the fields are in sorted order.
A small adjustment to his method solves this problem as well:
list_display = [f.name for f in Book._meta.fields]
Worked for me.
The problem with most of these answers is that they will break if your model contains ManyToManyField or ForeignKey fields.
For the truly lazy, you can do this in your admin.py:
from django.contrib import admin
from my_app.models import Model1, Model2, Model3
#admin.register(Model1, Model2, Model3)
class UniversalAdmin(admin.ModelAdmin):
def get_list_display(self, request):
return [field.name for field in self.model._meta.concrete_fields]
Many of the answers are broken by Django 1.10. For version 1.10 or above, this should be
list_display = [f.name for f in Book._meta.get_fields()]
Docs
Here is my approach, will work with any model class:
MySpecialAdmin = lambda model: type('SubClass'+model.__name__, (admin.ModelAdmin,), {
'list_display': [x.name for x in model._meta.fields],
'list_select_related': [x.name for x in model._meta.fields if isinstance(x, (ManyToOneRel, ForeignKey, OneToOneField,))]
})
This will do two things:
Add all fields to model admin
Makes sure that there is only a single database call for each related object (instead of one per instance)
Then to register you model:
admin.site.register(MyModel, MySpecialAdmin(MyModel))
Note: if you are using a different default model admin, replace 'admin.ModelAdmin' with your admin base class
Show all fields:
list_display = [field.attname for field in BookModel._meta.fields]
Every solution found here raises an error like this
The value of 'list_display[n]' must not be a ManyToManyField.
If the model contains a Many to Many field.
A possible solution that worked for me is:
list_display = [field.name for field in MyModel._meta.get_fields() if not x.many_to_many]
I like this answer and thought I'd post the complete admin.py code (in this case, I wanted all the User model fields to appear in admin)
from django.contrib import admin
from django.contrib.auth.models import User
from django.db.models import ManyToOneRel, ForeignKey, OneToOneField
MySpecialAdmin = lambda model: type('SubClass'+model.__name__, (admin.ModelAdmin,), {
'list_display': [x.name for x in model._meta.fields],
'list_select_related': [x.name for x in model._meta.fields if isinstance(x, (ManyToOneRel, ForeignKey, OneToOneField,))]
})
admin.site.unregister(User)
admin.site.register(User, MySpecialAdmin(User))
I'm using Django 3.1.4 and here is my solution.
I have a model Qualification
model.py
from django.db import models
TRUE_FALSE_CHOICES = (
(1, 'Yes'),
(0, 'No')
)
class Qualification(models.Model):
qual_key = models.CharField(unique=True, max_length=20)
qual_desc = models.CharField(max_length=255)
is_active = models.IntegerField(choices=TRUE_FALSE_CHOICES)
created_at = models.DateTimeField()
created_by = models.CharField(max_length=255)
updated_at = models.DateTimeField()
updated_by = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'qualification'
admin.py
from django.contrib import admin
from models import Qualification
#admin.register(Qualification)
class QualificationAdmin(admin.ModelAdmin):
list_display = [field.name for field in Qualification._meta.fields if field.name not in ('id', 'qual_key', 'qual_desc')]
list_display.insert(0, '__str__')
here i am showing all fields in list_display excluding 'id', 'qual_key', 'qual_desc' and inserting '__str__' at the beginning.
This answer is helpful when you have large number of modal fields, though i suggest write all fields one by one for better functionality.
list_display = [field.name for field in Book._meta.get_fields()]
This should work even with python 3.9
happy coding
I needed to show all fields for multiple models, I did using the following style:
#admin.register(
AnalyticsData,
TechnologyData,
TradingData,
)
class CommonAdmin(admin.ModelAdmin):
search_fields = ()
def get_list_display(self, request):
return [
field.name
for field in self.model._meta.concrete_fields
if field.name != "id" and not field.many_to_many
]
But you can also do this by creating a mixin, if your models have different fields.