I'm trying to code a blog with django but I want to add a placeholder to my form when creating or editing an article. So I had the forms.py because before that I wasn't using a form from this file because I only needed the models.py file. I fount a way to do what I wanted and so add my placeholder into my input from my forms. But one problem, when I updated my website and went to my pages to see the changed an error appeared.
So I tried to fix the problem by looking on the web and I saw a lot of people having approximately the same problem but the answers were that I had to add a get_queryset definition in my views in views.py for the specific forms. I didn't find what I have to set in the definition of the get_queryset and not very understood where I have to put these definitions. I would be very grateful if you can help me.
Here's my code :
My views in view.py :
class BlogHome(ListView):
model = BlogPost
context_object_name = "posts"
def get_queryset(self):
queryset = super().get_queryset()
if self.request.user.is_authenticated:
return queryset
else:
return queryset.filter(published=True)
#method_decorator(login_required, name='dispatch')
class BlogPostCreate(CreateView):
form_name = UpdatePostForm
class BlogPostEdit(UpdateView):
form_name = CreatePostForm
My urls.py :
urlpatterns = [
path('create/', BlogPostCreate.as_view(), name="create"),
path('edit/<str:slug>/', BlogPostEdit.as_view(), name="edit"),
My forms.py :
from django import forms
from posts.models import BlogPost
class UpdatePostForm(forms.Form):
model = BlogPost
template_name = 'posts/blogpost_edit.html'
fields = [
'title',
'slug',
'content',
'published',
'author',
'created_on'
]
class Meta:
title = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
slug = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
content = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
created_on = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the date of creation'}),
),
class CreatePostForm(forms.Form):
model = BlogPost
template_name = 'posts/blogpost_create.html'
fields = [
'title',
'slug',
'content',
'published',
'author',
'created_on'
]
class Meta:
title = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
slug = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
content = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
),
created_on = forms.CharField(
widget = forms.TextInput(attrs={'placeholder' : 'Enter the date of creation'}),
),
My models.py :
from django.contrib .auth import get_user_model
from django.template.defaultfilters import slugify
from django.db import models
from django import forms
from django.urls import reverse
User = get_user_model()
class BlogPost(models.Model):
title = models.CharField(max_length=255, unique=True, verbose_name="Titre")
slug = models.SlugField(max_length=255, unique=True, blank=True)
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
last_updated = models.DateTimeField(auto_now=True)
created_on = models.DateField(blank=True, null=True)
published = models.BooleanField(default=False, verbose_name="Publié")
content = models.TextField(blank=True, verbose_name="Contenu")
thumbnail = models.ImageField(blank=True, upload_to='blog')
class Meta:
ordering = ['-created_on']
verbose_name = "Article"
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
#property
def author_or_default(self):
return self.author.username if self.author else "L'auteur inconnu"
def get_absolute_url(self):
return reverse('posts:home')
class BlogPostCreate(CreateView):
form_class = UpdatePostForm
template_name = 'update_post.html'
success_url = 'success'
OR
class BlogPostCreate(CreateView):
model = UpdatePost
Try the above. Please remove #method_decorator(login_required, name='dispatch') from this class view because its a class view not a method.
Your form should be a model for I expect.
class CreatePostForm(forms.ModelForm):
I am updating my answer as per your last comment. Check this for django modelForm. You need to add a meta in your form:
class CreatePostForm(forms.ModelForm):
class Meta:
model = User
fields = ['...', ....]
Related
I created a ProductAttributes model that have a ForeignKey from Product model
now i'm trying to create an admin panel for adding product using django admin
i'm adding ProductAttributes to Product admin with TabularInline but its not working
this the models and admin classes
#models
class Product(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(null=True, blank=True)
introduction = models.TextField(null=True, blank=True)
unit_price = models.DecimalField(
max_digits=12,
decimal_places=2,
validators=[MinValueValidator(1)])
inventory = models.IntegerField(validators=[MinValueValidator(0)])
last_update = models.DateTimeField(auto_now=True)
collection = models.ForeignKey(Collection, on_delete=models.PROTECT, related_name='products')
promotions = models.ManyToManyField(Promotion, blank=True)
def __str__(self) -> str:
return self.title
class Meta:
ordering = ['title']
class ProductAttributes(models.Model):
Product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="attributes")
attribute = models.CharField(max_length=255)
#admin
class ProductAttributesInline(admin.TabularInline):
model = models.ProductAttributes
#admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
autocomplete_fields = ['collection']
prepopulated_fields = {
'slug': ['title']
}
actions = ['clear_inventory']
inlines = [ProductAttributesInline]
list_display = ['title', 'unit_price',
'inventory_status', 'collection_title']
list_editable = ['unit_price']
list_filter = ['collection', 'last_update', InventoryFilter]
list_per_page = 10
list_select_related = ['collection']
search_fields = ['title']
def collection_title(self, product):
return product.collection.title
#admin.display(ordering='inventory')
def inventory_status(self, product):
if product.inventory < 10:
return 'Low'
return 'OK'
#admin.action(description='Clear inventory')
def clear_inventory(self, request, queryset):
updated_count = queryset.update(inventory=0)
self.message_user(
request,
f'{updated_count} products were successfully updated.',
messages.ERROR
)
class Media:
css = {
'all': ['store/style.css']
}
the ProductAttributes isnt shown in Product admin
in the orginal project i created another inline for ProductImage and its working but when i try to delete that inline its not gone from product admin
Firstly, do not forget checking all migrations, and It would be more good to keep your models in models.py and do not mix them with admin related changes. I would recommend you to write them in admin.py.
You can use both images and attributes like that:
class ProductAttributesInlineAdmin(admin.TabularInline):
model = ProductAttributes
extra = 2
#admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
...
inlines = [ProductAttributesInlineAdmin, ProductImageInlineAdmin]
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']
i want to hide a specific line of my Django Admin Model by permission or Group
My models.py
class Post(models.Model):
title = models.CharField(max_length=128)
slug = AutoSlugField(populate_from='title')
category = models.CharField(max_length=64, choices=CATEGORY_CHOICES, default='actus')
is_verified = models.BooleanField(default=False)
content = RichTextField(blank=True, null=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
thumbnail = models.ImageField(upload_to='media/thumbs', blank=True, null=True, default="media/thumbs/default.jpg")
date = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post", kwargs={"slug": self.slug, "category": self.category})
My Model admin
from django.contrib import admin
from django.db import models
from django.db.migrations.graph import Node
from django.utils.regex_helper import Group
from .....models import Post
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'date', 'is_verified')
list_filter = ('date', 'author', 'is_verified')
admin.site.site_header = 'Staff Dashboard'
admin.site.register(Post, PostAdmin)
My django admin page
Django admin page
If someone has an idea
You can define two ModelForms: one with the is_verified option, and one without, so:
# app_name/forms.py
from django import forms
from app_name.models import Post
class NormalUserPostForm(forms.ModelForm):
class Meta:
model = Post
exclude = ['is_verified']
class AdminUserPostForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__'
then we can override the get_form method of the ModelAdmin:
# app_name/admin.py
from app_name.forms import NormalUserPostForm, AdminUserPostForm
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'date', 'is_verified')
list_filter = ('date', 'author', 'is_verified')
form = NormalUserPostForm
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs['form'] = AdminUserPostForm
return super().get_form(request, obj, **kwargs)
admin.site.site_header = 'Staff Dashboard'
admin.site.register(Post, PostAdmin)
You can change the condition to request.user.has_perm('some_permission') to check for a certain permission instead.
I'm working on a multi language application in Django with django-hvad.
I've two models, Category and Post for a Blog app:
class Category(TranslatableModel):
translations = TranslatedFields(
name=models.CharField(
max_length=100,
verbose_name=_(u'Nombre')
)
)
slug = AutoSlugField(
populate_from='name'
)
class Meta:
verbose_name = _(u'Categoría')
verbose_name_plural = _(u'Categorías')
def __unicode__(self):
return self.safe_translation_getter('name', str(self.pk))
class Post(TranslatableModel):
category = models.ForeignKey(
Category,
related_name='posts',
verbose_name=_(u'Categoría')
)
slug = AutoSlugField(
populate_from='title'
)
translations = TranslatedFields(
title=models.CharField(
max_length=100,
verbose_name=_(u'Título')
),
content=RichTextField(
verbose_name=_(u'Contenido')
)
)
class Meta:
verbose_name = _(u'Publicación')
verbose_name_plural = _(u'Publicaciones')
ordering = ['-created']
def __unicode__(self):
return self.safe_translation_getter('title', str(self.pk))
In my admin.py I'm registering my models this way:
from django.contrib import admin
from hvad.admin import TranslatableAdmin
from blog.models import Category, Post
class CategoryAdmin(TranslatableAdmin):
pass
admin.site.register(Category, CategoryAdmin)
class PostAdmin(TranslatableAdmin):
pass
admin.site.register(Post, PostAdmin)
When I'm creating a new Post in the admin interface I'm having Category IDs instead of their names in the category dropdown:
What should I do to have the translated name instead of the ID?
I tried to add search fields in Django using python. Followings are the codes that I have used.
# admin.py file
from django.db import models
from blog.models import Blog
from django.contrib import admin
admin.site.register(Blog)
class Blog(models.Model):
title = models.CharField(max_length=60)
body = models.TextField()
created = models.DateTimeField("Date Created")
updated = models.DateTimeField("Date Updated")
def __unicode__(self):
return self.title
class Comment(models.Model):
body = models.TextField()
author = models.CharField(max_length=60)
created = models.DateTimeField("Date Created")
updated = models.DateTimeField("Date Updated")
post = models.ForeignKey(Blog)
def __unicode__(self):
return self.body
class CommentInline(admin.TabularInline):
model = Comment
class BlogAdmin(admin.ModelAdmin):
list_display = ('title','created', 'updated')
search_fields = ['title','body']
list_filter = ('Date Created','Date Updated')
inlines = [CommentInline]
class CommentAdmin(admin.ModelAdmin):
list_display = ('post','author','body_first_60','created','updated')
list_filter = ('Date Created','Date Updated')
I tried to add a search_fields for title and body by using Following code.
class BlogAdmin(admin.ModelAdmin):
. . .
search_fields = ('title','body')
. . .
When I run this I can't see any search box. Why is that ? I want your help. I'm just a beginner.
Thanks!
The search fields should be a list, not a tuple.
class BlogAdmin(admin.ModelAdmin):
. . .
search_fields = ['title','body']
. . .
Then make sure that you associate this admin object with the model.
admin.site.register(Blog, BlogAdmin)
EDIT:
It's hard to tell from above, but you should consider just importing the models from models.py instead of redefining them in your admin.py file. Again, it looks like that's what you're doing above.
admin.py:
from django.db import models
from blog.models import Blog
from django.contrib import admin
class CommentInline(admin.TabularInline):
model = Comment
class BlogAdmin(admin.ModelAdmin):
list_display = ('title','created','updated',)
search_fields = ['title','body',]
list_filter = ('Date Created','Date Updated',)
inlines = [CommentInline,]
class CommentAdmin(admin.ModelAdmin):
list_display = ('post','author','body_first_60','created','updated',)
list_filter = ('Date Created','Date Updated',)
admin.site.register(Blog, BlogAdmin)
models.py
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=60)
body = models.TextField()
created = models.DateTimeField("Date Created")
updated = models.DateTimeField("Date Updated")
def __unicode__(self):
return self.title
class Comment(models.Model):
body = models.TextField()
author = models.CharField(max_length=60)
created = models.DateTimeField("Date Created")
updated = models.DateTimeField("Date Updated")
post = models.ForeignKey(Blog)
def __unicode__(self):
return self.body
You should register your site at the bottom of the site rather than at the top.
Please try admin.site.register(Blog, BlogAdmin) at the bottom of the page. I hope that will solve your question