This is the model that I want to show on the admin panel. I'm registering the model via admin.py file with admin.site.register(Ad). I tried to re-write the register line twice, and an exception appeared that the model is already registered.
class Ad(AdModel):
plate = models.CharField(max_length=50, unique=True)
description = models.TextField(max_length=500)
ad_type = models.CharField(
max_length=255,
choices=AdTypes.get_choices(),
default=AdTypes.OFFERING,
)
price = models.PositiveIntegerField(
default=0,
help_text='In cents'
)
location = models.CharField(
max_length=255,
choices=AdLocations.get_choices(),
default=AdLocations.VILNIUS,
)
user = models.ForeignKey(User, on_delete=models.PROTECT)
approved_date = models.DateField(null=True, blank=True)
approved_by = models.ForeignKey(
User, on_delete=models.PROTECT, related_name='approved_by', null=True
)
The two base models:
class UUIDBaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
class Meta:
abstract = True
class AdModel(UUIDBaseModel):
expires_at = models.DateTimeField(null=True)
is_draft = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
class Meta:
abstract = True
This is really strange, maybe that could be the problem because of the naming 'Ad'? I have a serializer for this model and everything works just fine, but the admin panel doesn't want to display it.
views.py
class AdCreateViewSet(ModelViewSet, CreateModelMixin):
serializer_class = AdCreateSerializer
permission_classes = (AllowAny,)
filter_backends = [DjangoFilterBackend]
search_fields = ('plate', 'description', 'user__email')
queryset = Ad.objects.select_related('user')
def perform_create(self, serializer):
user = User.objects.first()
serializer.save(user=user) # self.request.user)
serializers.py
class AdCreateSerializer(CustomAdSerializer):
class Meta:
model = Ad
exclude = ['expires_at']
read_only_fields = ('user',)
Related
We added the model named Comment as inlines in the Course model. We want to make it mandatory to fill in the fields in the Inlines model when the Save button is clicked.
# models.py
class Course(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
...
updated_at = models.DateTimeField(auto_now=True))
class Comment(models.Model):
CHOICES=[(1,'Approved'),
(0,'Rejected')]
course = models.ForeignKey(Course, on_delete=models.PROTECT)
opinion = models.IntegerField(choices=CHOICES)
comment = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# admin.py
class CommentInline(admin.StackedInline):
model = Comment
max_num = 1
radio_fields={'opinion':admin.HORIZONTAL}
#admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ('title', 'category', 'reviewer', 'created_at',)
inlines = [CommentInline,]
serializers.py
class RegSerializer(serializers.ModelSerializer):
admin = serializers.SlugRelatedField(slug_field='username', read_only=True)
class Meta:
model = Registration
fields = [
'id', 'rooms', 'first_name', 'last_name','admin', 'pasport_serial_num', 'birth_date', 'img', 'visit_date',
'leave_date', 'guest_count', 'room_bool']
models.py
class Rooms(models.Model):
objects = None
room_num = models.IntegerField(verbose_name='Комната')
room_bool = models.BooleanField(default=True, verbose_name='Релевантность')
category = models.CharField(max_length=150, verbose_name='Категория')
price = models.IntegerField(verbose_name='Цена (сум)', null=True)
def __str__(self):
return f'{self.room_num}'
class Meta:
verbose_name = 'Комнату'
verbose_name_plural = 'Комнаты'
class Registration(models.Model):
objects = None
rooms = models.ForeignKey(Rooms, on_delete=models.CASCADE, verbose_name='Номер',
help_text='Номер в который хотите заселить гостя!',
)
first_name = models.CharField(max_length=150, verbose_name='Имя')
last_name = models.CharField(max_length=150, verbose_name='Фамилия')
admin = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='Администратор')
pasport_serial_num = models.CharField(max_length=100, verbose_name='Серия паспорта', help_text='*AB-0123456')
birth_date = models.DateField(verbose_name='Дата рождения')
img = models.FileField(verbose_name='Фото документа', help_text='Загружайте файл в формате .pdf')
visit_date = models.DateField(
default=django.utils.timezone.localdate, verbose_name='Дата прибытия')
leave_date = models.DateField(blank=True, null=True, verbose_name='Дата отбытия', default='После ухода!')
guest_count = models.IntegerField(default=1, verbose_name='Кол-во людей')
room_bool = models.BooleanField(default=False, verbose_name='Релевантность',
help_text='При бронирование отключите галочку')
price = models.IntegerField(verbose_name='Цена (сум)', null=True)
def __str__(self):
return f'{self.rooms},{self.last_name},{self.first_name},{self.room_bool}'
class Meta:
verbose_name = 'Номер'
verbose_name_plural = 'Регистрация'
how can I make it so that the name of the user who registered room is indicated in the admin field and without the right to change only readonly?
can this be done at all?
thanks in advance for your reply
You can pass additional attributes to serilizer's save method. In your view, you can call serializer save() with admin argument like this:
def your_view(request):
# your code
serializer.save(admin=request.user)
Or if you want to do it on admin page, you can override your admin's save_model method. Also you should specify admin as a readonly:
class RegistrationAdmin(admin.ModelAdmin):
readonly_fields = ('admin',)
def save_model(self, request, obj, form, change):
if not obj.pk:
# Only set admin during the first save.
obj.admin = request.user
super().save_model(request, obj, form, change)
I set serializers.HiddenField and by default set CurrentUserDefault() from serializers
automatically substitutes the value of the current admin and at the same time the admin field now goes to the api
class RegSerializer(serializers.ModelSerializer):
admin = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Registration
exclude = ['price', 'visit_date']
Hello, I have a question about improving legacy models.
The Material model is old model, and i want to make category by using new model 'type'. But i have a little problem with when i use admin site. In admin site, i hope to choose the 'type' first, and upload data .. how can i make better
models
# new model
class MaterialType(BaseModel):
type = models.CharField(choices=MaterialTypeChoice.choices, max_length=50, null=True, blank=True)
def __str__(self):
return self.type
# old model
class Material(models.Model):
type = models.ForeignKey(MaterialType, verbose_name=, null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField max_length=50, null=True, blank=True)
size = models.CharField(max_length=50, null=True, blank=True)
unit = models.CharField(max_length=5, null=True, blank=True)
price_unit = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.name
serializers
# new
class MaterialTypeListSerializer(serializers.ModelSerializer):
class Meta:
model = MaterialType
fields = ["type"]
# old
class MaterialListSerializer(serializers.ModelSerializer):
class Meta:
model = Material
fields = ["id", "type", "name", "size", "unit", "price_unit"]
views
# new
class MaterialTypeList(ListCreateAPIView):
queryset = MaterialType.objects.all()
serializer_class = MaterialTypeListSerializer
# old
class MaterialList(ListAPIView):
queryset = Material.objects.all()
filter_class = MaterialFilter
serializer_class = MaterialListSerializer
admin
#admin.register(Material)
class MaterialAdmin(ImportExportModelAdmin):
list_display = ["name", "size", "unit", "price_unit"]
list_display_links = ("name",)
list_filter = ("type",)
list_per_page = 10
# list_editable = ('type',)
search_fields = ("name", "size")
resource_class = MaterialResource
#admin.register(MaterialType)
class MaterialTypeAdmin(ImportExportModelAdmin):
list_display = ["type"]
list_filter = ("type",)
list_per_page = 10
# list_editable = ('type',)
I am a bit stumped as to how I can add multiple access_token and items_ids in Django Admin. The models and apps involved are as follows. This is my first post so please forgive if it isn't in proper format.
Trans/models.py
class Exchange(models.Model):
created = models.DateTimeField()
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='token', on_delete=models.CASCADE)
access_token = models.CharField(max_length=300, blank=True, default='')
item_id = models.CharField(max_length=300, blank=True, default='')
request_id = models.CharField(max_length=300, blank=True, default='')
class Meta:
ordering = ('item_id',)
I have setup a userprofile section for the admin:
Users/models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, verbose_name='user', related_name='profile', on_delete=models.CASCADE)
avatar_url = models.CharField(max_length=256, blank=True, null=True)
dob = models.DateField(verbose_name="dob", blank=True, null=True)
public_token = models.CharField(max_length=100, blank=True, null=True, verbose_name='public_token')
access_token = models.CharField(max_length=100, blank=True, null=True, verbose_name='access_token')
item_id = models.CharField(max_length=100, blank=True, null=True, verbose_name='item_ID')
just_signed_up = models.BooleanField(default=True)
def __str__(self):
return force_text(self.user)
class Meta():
db_table = 'user_profile'
users/forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('user', 'public_token', 'access_token', 'item_id',)
users/admin.py
class UserProfileAdmin(admin.ModelAdmin):
search_fields = ('user', 'dob', 'public_token', 'access_token', 'item_id',)
ordering = ('user',)
list_select_related = ('user',)
admin.site.register(UserProfile, UserProfileAdmin)
class UserProfileAdminInline(admin.TabularInline):
model = UserProfile
I'm really just stumped as I tried making many to many field but couldnt seem to link correctly and or the process broke when testing in a sandbox environment. Any help would be greatly appreciated! In my case I need to record multiple access_tokens and item_ids for each user.
It's a little bit confusing what you are asking...particularly the way that your data model is setup....but I'm going to make a couple of assumptions in my answer (it would be helpful to better understand what you are trying to do at a high level).
I think what you are wanting to do is to be able to configure multiple Exchange objects per user profile...in which case I would set things up this way:
1. The related_name field on the FK to the user profile in the exchange model will be how you access multiple exchanges...so in this case you probably want a pluralized name.
2. To be able to edit multiple in the Django Admin you will need to setup an InlineAdmin object.
3. The CharFields that are actually ON the UserProfile will only ever be single fields...if you want multiple then you need to move them to another related object (like the Exchange model).
4. I don't think what you want here is a ManyToMany as that would imply user's would be sharing these tokens and item ids (or Exchanges?)...but maybe that is what you want...in which case you should change the ForeignKey to UserProfile from the Exchange model to a ManyToManyField. The rest of this post assumes you don't want that.
trans/models.py
from django.db import models
from django.conf import settings
class Exchange(models.Model):
class Meta:
ordering = ('item_id', )
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='exchanges', on_delete=models.CASCADE)
access_token = models.CharField(max_length=300, blank=True)
item_id = models.CharField(max_length=300, blank=True)
request_id = models.CharField(max_length=300, blank=True)
users/models.py
from django.db import models
from django.conf import settings
class UserProfile(models.Model):
class Meta:
db_table = 'user_profile'
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, verbose_name='user', related_name='profile', on_delete=models.CASCADE)
avatar_url = models.CharField(max_length=256, blank=True)
dob = models.DateField(verbose_name="dob", blank=True, null=True)
public_token = models.CharField(max_length=100, blank=True, null=True)
access_token = models.CharField(max_length=100, blank=True, null=True)
item_id = models.CharField(max_length=100, blank=True, null=True)
just_signed_up = models.BooleanField(default=True)
def __str__(self):
return force_text(self.user)
users/admin.py
from django.contrib import admin
from trans.models import Exchange
from users.models import UserProfile
class ExchangeAdminInline(admin.TabularInline):
model = Exchange
class UserProfileAdmin(admin.ModelAdmin):
inlines = (ExchangeAdminInline, )
search_fields = ('user', 'dob', 'public_token', 'access_token', 'item_id', )
ordering = ('user', )
list_select_related = ('user', )
admin.site.register(UserProfile, UserProfileAdmin)
There is a lot that you can do to configure the inlines to behave how you want...but that's the basics.
I just started toying around with the Django Rest Framework, so I'm still not entirely sure what exactly is going on. But I have a user model, a friend model, and a post model, I also have my serializers and views in order. But, I can't figure out how to return all the posts from my user's friends. Any help would be greatly appreciated.
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField('email address', unique=True, db_index=True)
password1 = models.CharField(max_length=50)
username = models.CharField('username', max_length=50, unique=True, db_index=True)
image = models.FileField(upload_to='photos', null=True, blank=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __unicode__(self):
return self.username
class Meta:
unique_together = (('username', 'password1'),)
class Friendship(models.Model):
created_at = models.DateTimeField(auto_now_add=True, editable=False)
creator = models.ForeignKey(CustomUser, related_name="friendship_creator")
friend = models.ForeignKey(CustomUser, related_name="friends")
class Post(models.Model):
poster = models.ForeignKey(CustomUser)
body = models.CharField(max=200)
def save(self, *args, **kwargs):
super(Post, self).save(*args, **kwargs)
serializers.py
class FriendSerializer(HyperlinkedModelSerializer):
class Meta:
model = Friendship
fields = ('creator', 'friend', 'created_at')
readonly_fields = 'created_at'
class CustomUserSerializer(HyperlinkedModelSerializer):
friends = FriendSerializer(many=True)
class Meta:
model = CustomUser
fields = ('email', 'username', 'password1', 'image', 'friends')
readonly_fields = 'image'
views.py
class FriendViewSet(ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = FriendSerializer
class UserProfileViewSet(RetrieveModelMixin, UpdateModelMixin, GenericViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
This may get you started,
So what you need to do first is get all the friends, you can do that by using
friends = <user_objects>.Friendship_set.all()
Read more about is here.
Now that you have all the friends of that particular user, covert their IDs to list and use the in list filter.
Post.objects.filter(poster__id__in=[list_of_ids_of_friends])
See this answer for filtering on foreign key properties.