I dont see models in django-admin which created from drf - python

I create and save user from django-rest-framework, but it do when i am anonymous user. Now i dont see those model in django-admin. How to add model to django-admin?
admin.py
from django.contrib import admin
from possible_blacklist.models import PossibleBlacklist
class PossibleBlacklistAdmin(admin.ModelAdmin):
list_display = [field.name for field in PossibleBlacklist._meta.get_fields()]
admin.site.register(PossibleBlacklist, PossibleBlacklistAdmin)
serializers.py
from rest_framework import serializers
from possible_blacklist.models import PossibleBlacklist
class PossibleBlacklistSerializer(serializers.ModelSerializer):
class Meta:
model = PossibleBlacklist
fields = '__all__'
def create(self, validated_data):
return PossibleBlacklist.objects.create(**validated_data)
def validate_mobile_phone(self, data):
if data.startswith('0'):
raise serializers.ValidationError("Номер должен начинаться на +380")
return data

I had this problem and when I research, I've found this good documentation which will add the model automatically to your Django admin interface.
and no need to touch your admin with every single model which are you adding.
https://medium.com/hackernoon/automatically-register-all-models-in-django-admin-django-tips-481382cf75e5

Related

Not all fields are showing correctly in django admin

I've added a plan field to my custom Account class, but cannot get it to show on the individual account page in the django admin. It shows correctly in table of all accounts in the list view (as denoted by list_display), but does not show on each individual account page.
Here's my Account model:
class Account(AbstractUser):
PLANS = (
("free", "free"),
("pro", "pro")
)
plan = models.CharField(max_length=10, choices=PLANS, default="free")
def __str__(self) -> str:
return self.first_name
And my admin file:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber
class SubscriberInline(admin.TabularInline):
model = Subscriber
extra = 0
class AccountAdmin(UserAdmin):
inlines = [SubscriberInline, ]
list_display = ("first_name", "plan", "email")
# fields = ("first_name", "plan", "email")
admin.site.register(Account, AccountAdmin)
Why does this happen?
Is the problem related to the custom Account class which inherits from the AbstractUser model? I thought to add fields to the AccountAdmin class, but that just returns the below error:
ERRORS:
<class 'accounts.admin.AccountAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.
The plan field also doesn't show in the admin panel when trying to create a new account (mind you, neither do most of the other fields as it only asks for the username, password1 and password2 fields, and the option to add new subscribers to the table, but other fields like first_name etc can be edited in the admin after creation).
Thanks
UPDATE:
Adding user #bdbd's suggested changes seems to not make a difference to the admin area - am I adding this incorrectly? Here's my admin.py after adding #bdbd's changes:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber
from django.contrib.auth.forms import UserChangeForm
from django import forms
PLANS = (
("free", "free"),
("pro", "pro")
)
class MyAccountChangeForm(UserChangeForm):
plan = forms.ChoiceField(choices=PLANS)
class SubscriberInline(admin.TabularInline):
model = Subscriber
extra = 0
class AccountAdmin(UserAdmin):
form = MyAccountChangeForm
inlines = [SubscriberInline, ]
list_display = ("first_name", "plan", "email")
# #todo: bug! plan field not showing in django admin on individual account pages
admin.site.register(Account, AccountAdmin)
UPDATE 2:
Screenshots of admin area:
You should not extend from UserAdmin. Instead, you should create your own model admin class which extends from admin.ModelAdmin.
Then you should register your model separately.
class AccountAdmin(admin.ModelAdmin):
...
admin.site.register(Account, AccountAdmin)
As necessary, you can customize AccountAdmin to get the effect you want. You can peek at the UserAdmin source code to see how it is customized, if you want your admin view to behave similarly.
You need to override the default form that is being used by UserAdmin and add your field like so:
from django.contrib.auth.forms import UserChangeForm
from django import forms
class MyAccountChangeForm(UserChangeForm):
plan = forms.ChoiceField(choices=PLANS)
Then assign the form to your admin:
class AccountAdmin(UserAdmin):
form = MyAccountChangeForm

How to add an extra field to a Django ModelForm?

So I'm working on an admin page. I'm registering the form with admin.site.register. And I want to add an extra field to the form, which will let me populate a TextField with a file contents.
Therefore I need to add an extra FileInput to upload the file and populate the TextField with its contents. I am trying this:
class PersonForm(forms.ModelForm):
extra_field = forms.FileInput()
class Meta:
model = Person
fields = '__all__'
but the field is not showing. Any ideas?
Also I have no clue where to access the file contents and populate the TextField with that before saving the model.
Thanks in advance.
My problem was in this line:
extra_field = forms.FileInput()
I solved the problem changing the line to:
extra_field = forms.FileField()
Thanks to all willing to help.
Try to do it in the constructor.
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = '__all__'
def __init__(self, *args, **kwargs):
super(PersonForm, self ).__init__(*args, **kwargs)
self.fields['extra_field'] = forms.FileInput()
And since you are using the django admin, you need to change the form in the admin too.
What you've done is ok according to the documentation, read note here - https://docs.djangoproject.com/en/2.0/topics/forms/modelforms/#overriding-the-default-fields
To register it in the admin you should add something like this to your admin.py:
from django.contrib import admin
from .forms import PersonForm
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
form = PersonForm
Example from here - https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#admin-custom-validation
EDIT: it is necessary to actually register custom ModelAdmin, there are two equivalent ways: using decorator, as in the example above, or use admin.site.register(Person, PersonAdmin).
Documentation for ModelAdmin registration - https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#the-register-decorator
Registration source code - https://github.com/django/django/blob/master/django/contrib/admin/sites.py#L85
Register the model in admin as
admin.site.register(UserProfile)
where UserProfile is a OnetoOnemodel that extends django's builtin User Model then after every changes in models run
python manage.py makemigrations
python manage.py migrate

How to move model to the other section in Django's site admin

Is it possible to move default Groups model from 'Authentication and Authoriation' section (on the Django admin site) to custom one and how to achieve that?
Let's start from the beginning in the other words.
I have a very simple application 'accounts' in my Django project.
models.py file looks like below:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
def __str__(self):
return self.email
serializers.py file:
from rest_framework import serializers
from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
class UserSerializer(serializers.HyperlinkedModelSerializer):
groups = serializers.HyperlinkedRelatedField(
many=True,
required=False,
read_only=True,
view_name="group-detail"
)
class Meta:
model = get_user_model()
exclude = ('user_permissions',)
Now, on the admin site I have two sections: 'Accounts' and 'Authentication and Authorization'. 'Accounts' section contains my 'Users' table (for User model) and 'Authentication and Authorization' section contains 'Groups' table (for Django's default authorization Group model).
My question is - is it possible and how to move Groups table (model) to the 'Accounts' section?
I've even tried to create a custom 'Group' model based on Django's default auth Group model but have stuck on migration exceptions.
Is it possible to move default Groups model from 'Authentication and Authoriation' section (on the Django admin site) to custom one and how to achieve that?
Yes, it's possible.
1) You can move your model to section auth, just add to your class:
class Meta:
app_label = 'auth'
2) You can move Group and User models to your app section, for that variant need to:
Override user model and add it to your app
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
pass
also need add to your project settings AUTH_USER_MODEL = 'your_app.CustomUser'
Don't forget declare in admin.py from your app:
class UserAdmin(admin.ModelAdmin):
pass
admin.site.register(CustomUser, UserAdmin)
For group model put this code in admin.py:
from django.db.models.loading import get_models
from django.contrib.auth import models
models = get_models(models)
models[1]._meta.app_label = 'your_app'
3) You can look at django-admin-tools

Extending the user profile in Django. Admin creation of users

Good evening,
I am presently creating a site with Django and I extended the user with a user profile. I have a small problem though. Here is my situation:
I extended the user profile in order to add custom fields.
I added the model to the User Admin Model, so when I am adding a user, I can fill in directly the fields to create the profile.
Now, if I don't add ANYTHING in these new custom user fields, in the user add page, Django Admin won't throw me an error saying these fields are null (and they aren't suppose to be)
I want it to throw me an error in this User Add Admin page, so that the admins will HAVE to fill in a profile when adding a new user.
ALL the users will be added in the Admin Panel.
Is this possible? Thanks a lot!
in admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.contrib.auth.models import User
from accounts.models import UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
class UserAdmin(DjangoUserAdmin):
inlines = [ UserProfileInline,]
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
In model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
employee_number = models.PositiveIntegerField(unique=True)
def __unicode__(self):
return 'Number'
By default, empty inline is permitted and thus no further check would be taken for an empty form. You need to override it manually:
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if self.instance.pk is None:
self.empty_permitted = False # Here
class Meta:
model = UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
form = UserProfileForm

How to add custom fields to InlineFormsets?

I'm trying to add custom fields to an InlineFormset using the following code, but the fields won't show up in the Django Admin. Is the InlineFormset too locked down to allow this? My print "ding" test fires as expected, I can print out the form.fields and see them all there, but the actual fields are never rendered in the admin.
admin.py
from django.contrib import admin
import models
from django.forms.models import BaseInlineFormSet
from django import forms
from forms import ProgressForm
from django.template.defaultfilters import slugify
class ProgressInlineFormset(BaseInlineFormSet):
def add_fields(self, form, index):
print "ding"
super(ProgressInlineFormset, self).add_fields(form, index)
for criterion in models.Criterion.objects.all():
form.fields[slugify(criterion.name)] = forms.IntegerField(label=criterion.name)
class ProgressInline(admin.TabularInline):
model = models.Progress
extra = 8
formset = ProgressInlineFormset
class ReportAdmin(admin.ModelAdmin):
list_display = ("name", "pdf_column",)
search_fields = ["name",]
inlines = (ProgressInline,)
admin.site.register(models.Report, ReportAdmin)
I did it another way:
forms.py:
from django import forms
class ItemAddForm(forms.ModelForm):
my_new_field = forms.IntegerField(initial=1, label='quantity')
class Meta:
model = Item
admin.py:
from django.contrib import admin
from forms import *
class ItemAddInline(admin.TabularInline):
form = ItemAddForm
fields = (..., 'my_new_field')
This works so far, I only need to override somehow the save method to handle this new field. See this: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#form . It says that by default Inlines use BaseModelForm, which is send to formset_factory. It doesn't work for me, tried to subclass BaseModelForm with errors (no attribute '_meta'). So I use ModelForm instead.
You can do it by another way (Dynamic forms):
admin.py
class ProgressInline(admin.TabularInline):
model = models.Progress
extra = 8
def get_formset(self, request, obj=None, **kwargs):
extra_fields = {'my_field': forms.CharField()}
kwargs['form'] = type('ProgressForm', (forms.ModelForm,), extra_fields)
return super(ProgressInline, self).get_formset(request, obj, **kwargs)
model = models.Progress
In the admin there will be only the fields defined in this Progress model. You have no fields/fieldsets option overwriting it.
If you want to add the new ones, there are two options:
In the model definition, add those new additional fields (make them optional!)
In the admin model (admin.TabularInline), add something something like:
fields = ('newfield1', 'newfield2', 'newfield3')
Take a look at fields, fieldsets.

Categories