Garrett
Garrett

Reputation: 1808

Display form fields depending on user

So I have a social network where users can post thinks. I would like to incorporate a blog system into the same feed app instead of making blog its own app. I was thinking that if I (or someone with adequate permissions) wanted to make a blog post they could use the same form used by everyone to make a post, however since they have higher permissions they would be shown an extra option on the form that allows them to make it a blog post. and on the blog page I would just filter out to only have posts with blog_post set to true to be shown.

I tried to do this with a simple if statement in the forms.py however I get an error:

Traceback (most recent call last):
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 125, in inner_run
    self.check(display_num_errors=True)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/management/base.py", line 359, in check
    include_deployment_checks=include_deployment_checks,
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/management/base.py", line 346, in _run_checks
    return checks.run_checks(**kwargs)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/checks/urls.py", line 16, in check_url_config
    return check_resolver(resolver)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/core/checks/urls.py", line 26, in check_resolver
    return check_method()
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/urls/resolvers.py", line 254, in check
    for pattern in self.url_patterns:
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/urls/resolvers.py", line 405, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/urls/resolvers.py", line 398, in urlconf_module
    return import_module(self.urlconf_name)
  File "/anaconda/envs/test/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 978, in _gcd_import
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File "/Users/garrettlove/Desktop/evverest/evverest/urls.py", line 20, in <module>
    from feed import views
  File "/Users/garrettlove/Desktop/evverest/feed/views.py", line 4, in <module>
    from feed.forms import PostForm,CommentForm
  File "/Users/garrettlove/Desktop/evverest/feed/forms.py", line 7, in <module>
    class PostForm(forms.ModelForm):
  File "/anaconda/envs/test/lib/python3.6/site-packages/django/forms/models.py", line 248, in __new__
    "needs updating." % name
django.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited; form PostForm needs updating.

forms.py:

from django.contrib.auth import get_user_model
User = get_user_model()

class PostForm(forms.ModelForm):
    class Meta:
        model = UserPost

        if User.username == 'garrett':
            fields = ('title','image','post_body','blog_post')
        else:
            fields = ('title','image','post_body')

        widget = {
            'title':forms.TextInput(attrs={'class':'post-title'}),
            'post_body':forms.Textarea(attrs={'class':'post-body'}),
        }

models.py:

from django.contrib.auth import get_user_model
User = get_user_model()

# Create your models here.
class UserPost(models.Model):
    author = models.ForeignKey(User,related_name='userpost',null=True)
    post_date = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=150,blank=False)
    post_body = models.TextField(max_length=1000,blank=False)
    image = models.ImageField(upload_to='post_pics',blank=True)
    blog_post = models.BooleanField(default=False)

    class Meta:
        ordering = ['-post_date']

    def publish(self):
        self.save()

    def get_absolute_url(self):
        return reverse('index')

    def __str__(self):
        return self.title

Views.py:

from django.shortcuts import render,get_object_or_404,redirect
from django.utils import timezone
from feed.models import UserPost,UserComment
from feed.forms import PostForm,CommentForm
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required

from django.contrib.auth import get_user_model

from django.contrib.auth.mixins import LoginRequiredMixin
from braces.views import SelectRelatedMixin

from django.views.generic import (TemplateView,ListView,
                                    DetailView,CreateView,
                                    UpdateView,DeleteView)

User = get_user_model()

# Create your views here.

##Posts Views
class HomeView(LoginRequiredMixin,ListView):
    login_url = 'account_login'
    model = UserPost

class CreatePostView(LoginRequiredMixin,CreateView):
    login_url = 'users:user_login'
    redirect_field_name = '/userpost_list.html'
    model = UserPost
    form_class = PostForm

    def form_valid(self,form):
        form.instance.author = self.request.user
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save()
        return super(CreatePostView, self).form_valid(form)

class PostDetailView(DetailView):
    model = UserPost
    post_comments = UserComment.objects.all()
    context = {
            'post':model,
            'comments':post_comments,
            }

class UpdatePostView(LoginRequiredMixin,UpdateView):
    login_url = '/login/'
    model = UserPost
    fields = [
            'title',
            'post_body',
            ]
    template_name_suffix = '_edit_form'

    def get_success_url(self):
        postid = self.kwargs['pk']
        return reverse_lazy('index')

@login_required
def DeletePost(request,pk):
    post = get_object_or_404(UserPost,pk=pk)
    post.delete()
    return redirect('index')

##Comments Views
@login_required
def add_comment_to_post(request,pk):
    post = get_object_or_404(UserPost,pk=pk)
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.author = request.user
            comment.save()
            return redirect('feed:post_detail', pk=post.pk)
    else:
        form = CommentForm()
    return render(request,'feed/comment_form.html',{'form':form})

@login_required
def comment_remove(request,pk):
    comment = get_object_or_404(UserComment,pk=pk)
    post_pk = comment.post.pk
    comment.delete()
    return redirect('feed:post_detail',pk=post_pk)


##BLOG VIEWS
class BlogView(ListView):
    model = UserPost

Upvotes: 0

Views: 77

Answers (2)

user8060120
user8060120

Reputation:

in your view need add user to kwargs:

class CreatePostView(LoginRequiredMixin,CreateView):
    # Your code here
    def get_form_kwargs(self):
        kwargs = super(CreatePostView, self).get_form_kwargs()
        kwargs.update({'user': self.request.user})
        return kwargs

after it use __init__ method (i correct it with Daniel solution)

class PostForm(forms.ModelForm):
    class Meta:
        model = UserPost
        fields = ('title','image','post_body','blog_post')

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(PostForm, self).__init__(*args, **kwargs)
        if not user.username == 'garrett':
            self.fields.pop('blog_post')

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 600059

This can't possibly work in this way. This is all evaluated when the class is defined, long before there are any users. And User is the class itself, not an instance of it; User.username is just a CharField object, not an actual username.

Instead, you need to set the full list of fields as default, but in the form's __init__ method you take the current user and modify the actual fields as necessary.

class PostForm(forms.ModelForm):
    class Meta:
        model = UserPost
        fields = ('title','image','post_body','blog_post')
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(PostForm, self).__init__(*args, **kwargs)
        if user.username != 'garrett'
            del self.fields['blog_post']

Upvotes: 1

Related Questions