Accessing SubClassed User Profile Module in Django 1.3 - django

I am trying to create two user types in django 1.3. I am subclassing the AUTH_PROFILE_MODULE with the following models.py:
class Member(models.Model):
ROLE_CHOICES = (
(0, 'Guide'),
(1, 'Operator'),
)
user = models.ForeignKey(User, unique=True)
location = models.CharField(max_length=60)
role = models.IntegerField(choices=ROLE_CHOICES)
class Guide(Member):
bio = models.TextField(blank=True)
experience = models.TextField(blank=True)
image = models.ImageField(blank=True, upload_to='images')
fileupload = models.FileField(blank=True, upload_to='files')
def __unicode__(self):
return self.user.username
def get_absolute_url(self):
return '/profiles/guides/%s' % self.user.username
class Operator(Member):
bio = models.TextField(blank=True)
image = models.ImageField(blank=True, upload_to='images')
def __unicode__(self):
return self.user.username
def get_absolute_url(self):
return '/profiles/operators/%s' % self.user.username
I am using generic class based views and can get the ListView to work for the Guide and Operator models I cannot get the DetailView to work. My views.py is as follows:
class GuideDetailView(DetailView):
model = Guide
context_object_name = 'guide'
template_name = 'members/guide_detail.html'
class GuideListView(ListView):
model = Guide
context_object_name = 'guides'
template_name = 'members/guide_list.html'
Any idea what might be missing?

Either provide a queryset:
class GuideDetailView(DetailView):
queryset = Guide.objects.all()
or override the get Method of DetailView:
class GuideDetailView(DetailView):
def get(self):
return "Everything you want, maybe: Guide.object.get(id=1)"
Given this in your urls.py:
url(r'^(?P<my_id>\d)/$', GuideDetailView.as_view(),),
You need to override get, like this:
class GuideDetailView(DetailView):
def get(self, request, **kwargs):
# lookup Guide Id in your database and assign it object
self.object = Guide.objects.get(pk=kwargs.get('my_id'))
# add object to your context_data, so that you can access via your template
context = self.get_context_data(object=self.object)
return self.render_to_response(context)

Related

how to stop create view if already created django

please help me in making this application in django project
Here is models.py file code
from django.db import models
from bio.models import Profile
class Question(models.Model):
name = models.TextField(max_length=500)
def __str__(self):
return self.name
class Answer(models.Model):
question = models.ForeignKey(Question, related_name='question', on_delete=models.CASCADE)
profile = models.ForeignKey(Profile, related_name='profile', on_delete=models.CASCADE)
text = models.TextField(max_length=400)
created_on = models.DateTimeField(auto_now_add=True,null=True)
def __str__(self):
return "{0} on {1}".format(self.question, self.profile)
class Meta:
db_table = 'answer'
constraints = [
models.UniqueConstraint(fields=['profile', 'text', 'question'], name='unique answer')
]
here is views.py file code
class DetailViewMixin(object):
details_model = None
context_detail_object_name = None
def get_context_data(self, **kwargs):
context = super(DetailViewMixin, self).get_context_data(**kwargs)
context[self.context_detail_object_name] = self.get_detail_object()
return context
def get_detail_object(self):
return self.details_model._default_manager.get(pk=self.kwargs['pk'])
class AnswerCreate(DetailViewMixin, CreateView):
details_model = Question
context_detail_object_name = 'question'
model = Answer
form_class = NewAnswerForm
template_name = "qna/answer.html"
success_url = reverse_lazy('qna:list')
def form_valid(self, form):
form.instance.profile_id = self.kwargs.get('pk')
form.instance.question_id = self.kwargs.get('pk')
return super().form_valid(form)
here is my forms.py code
from django import forms
from .models import Answer
class NewAnswerForm(forms.ModelForm):
class Meta:
model = Answer
fields = ['text',]
def clean(self):
try:
Answer.objects.get(text=self.cleaned_data['text'].lower())
raise forms.ValidationError('Answer exists!')
except Answer.DoesNotExist:
pass
return self.cleaned_data
where am I going wrong????
I want that if user answers one question then he couldn't answer it again
how can i do form validation if object is already created
Add a UniqueConstraint to Answer so no combination of Question and Profile can be repeated:
https://docs.djangoproject.com/en/3.1/ref/models/constraints/#django.db.models.UniqueConstraint

How to rename file before saving it to database in django rest_framework

class GenericAPIView(generics.GenericAPIView, mixins.ListModelMixin,mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin ):
serializer_class = userdataSerializer
queryset = UserData.objects.all()
lookup_field = 'id'
def get(self, request, id=None):
if id:
return self.retrieve(request)
else:
return self.list(request)
def post(self, request):
return self.create(request)
def put(self, request, id=None):
return self.update(request, id)
//////////////////// models.py //////////////////////////
class UserData(models.Model):
user = models.OneToOneField(User, default="", on_delete=models.CASCADE)
user_phn = models.IntegerField(default=0)
user_verification_id = models.ImageField(upload_to='users/documents', default="no-img.png")
user_linkedin_id = models.CharField(max_length=200)
user_twitter_id = models.CharField(max_length=200)
user_cv = models.FileField(upload_to='users/cv', default="no-img.png")
user_about = models.CharField(max_length=500)
user_bal = models.FloatField(default=0.0)
class Meta:
verbose_name_plural = "Userdata"
def __str__(self):
return str(self.user)
///////////////////////////// serializer.py ///////////////////////////
from rest_framework import serializers
from users.models import UserData
import uuid
users serializer
class userdataSerializer(serializers.ModelSerializer):
class Meta:
model = UserData
fields = ['user_phn','user_verification_id','user_linkedin_id','user_twitter_id','user_cv','user_about','user_bal','user_id']
I want to rename CV and image before saving it to database
As you are using CreateModelMixin, you can add a perform_create function to your view function to customize the image and file names.
def perform_create(self, serializer):
serializer.validated_data['user_verification_id'].name = 'foo_image_name'
serializer.validated_data['user_cv'].name = 'foo_cv_name'
serializer.save()
You can rename your file using the by assigning a function to your filefield like below.
def user_directory_path(instance, filename):
# filename = TODO : logic to change your filename
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)
and your model filefield declaration should be like below.
user_cv = models.FileField(upload_to=user_directory_path)
I hope this will help you :)

How to reference a slug from a different model in get_success_url?

Setup
I have two models in my app. One is for a Journal and the other one is for entries to that journal. I wrote a CreateView class that will allow user to create a Journal entry for any Journal id currently located in. Ideally I want the class to "refresh" with the updated entry or in other words the get_success_url should lead the page we are currently located at.
views.py
class ToJournalEntriesList(LoginRequiredMixin, CreateView):
model = to_journal_entry
template_name = 'to_journals/to_journal_entries_list.html'
fields = ('body',)
def get_success_url(self):
return reverse('to-journals', kwargs={'slug':self.object.slug})
def form_valid(self, form):
current_journal = to_journal.objects.get(journal_user=self.request.user, slug=self.kwargs['slug'])
form.instance.journal_user = self.request.user
form.instance.journal_name = current_journal
return super(ToJournalEntriesList, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(ToJournalEntriesList, self).get_context_data(**kwargs)
context['to_journal_entries'] = to_journal_entry.objects.all()
return context
models.py
class to_journal(models.Model):
journal_name = models.CharField(max_length = 40)
slug = AutoSlugField(populate_from='journal_name')
date_created = models.DateTimeField(auto_now_add=True)
journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
def __str__(self):
return str(self.journal_user) + " " + self.journal_name
def get_absolute_url(self):
return reverse('to-journals')
class to_journal_entry(models.Model):
body = models.TextField()
entry_date = models.DateTimeField(auto_now_add=True)
journal_name = models.ForeignKey(to_journal, on_delete=models.CASCADE,)
journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
def __str__(self):
return str(self.journal_name) + " " + str(self.entry_date)
def get_absolute_url(self):
return reverse('to-journal-entries', args=(self.slug))
urls.py
urlpatterns = [
path('', CreateToJournal.as_view(), name='to-journals'),
path('<slug:slug>', ToJournalEntriesList.as_view(), name='to-journal-entries'),
]
Error
With the current setup that I have I get:
Which makes sense, because the to_journal_entry model does not have that that field.
Question
I am sure both my get_success_url() in views.py and get_absolute_url() in models.py are done incorrectly, but I could not find a good explanation of how those work. How should I set them up to achieve desired result? Thanks a ton in advance!
I appreciate everyone taking a look. Best, Rasul.
You can just follow the relationship:
def get_success_url(self):
return reverse('to-journals', kwargs={'slug': self.object.journal_name.slug})
Your self.object is a to_journal_entry. You probably want to use the to_journal, you can do that by obtaining the journal_name:
class ToJournalEntriesList(LoginRequiredMixin, CreateView):
model = to_journal_entry
template_name = 'to_journals/to_journal_entries_list.html'
fields = ('body',)
def get_success_url(self):
return reverse('to-journals', kwargs={ 'slug': self.object.journal_name.slug })
Note: usually the names of the models are written in PerlCase, so JournalEntry instead of to_journal_entry.

Redirection issue using PK

I Have a very strange phenomenon
In my app the user Create a project and is redirected to that project detail using its pk. On that project detail page he is asked to create a team and when the team is created he is redirected again to the project detail page but to the wrong pk
for example: I just created a project and I got redirected to .../project/24. I was asked to create a team, I created it but got redirected to ../project/17 any idea why and how to redirect my page to the right URL ?
model.py:
class Team(models.Model):
team_name = models.CharField(max_length=100, default = '')
team_hr_admin = models.ForeignKey(MyUser, blank=True, null=True)
def get_absolute_url(self):
return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk})
def __str__(self):
return self.team_name
class TeamMember(models.Model):
user = models.ForeignKey(MyUser)
team = models.ForeignKey(Team)
def __str__(self):
return self.user.first_name
class Project(models.Model):
name = models.CharField(max_length=250)
team_id = models.ForeignKey(Team, blank=True, null=True)
project_hr_admin = models.ForeignKey(MyUser, blank=True, null=True)
def get_absolute_url(self):
return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk})
def __str__(self):
return self.name
views.py
class TeamCreate(CreateView):
model = Team
fields = ['team_name']
template_name = 'team_form.html'
def form_valid(self, form):
valid = super(TeamCreate, self).form_valid(form)
form.instance.team_hr_admin = self.request.user
obj = form.save()
#SELECT * FROM project WHERE user = 'current_user' AND team_id = NULL
obj2 = Project.objects.get(project_hr_admin=self.request.user, team_id=None)
obj2.team_id = obj
obj2.save()
return valid
return super(TeamCreate, self).form_valid(form)
def get_success_url(self):
project = Project.objects.get(team_id=self.obj, project_hr_admin=self.request.user)
return project.get_absolute_url()
The problem here is your CreateView is refering to a TeamObject and not project.
You should override the get_success_url method:
def get_success_url(self):
project = Porject.objects.get(team_id=self.object, project_hr_admin=self.request.user)
return project.get_absolute_url()
The function called was the get_absolute_url of your Team model. So you're calling the project detail view but with the team pk => you get a random project assuming there's a project with a pk which has the same value as your project or, the pk you're sending doesn't exist and you'll have a 404 error (pk doesn't exist).
def get_absolute_url(self):
return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk})
That's the one in your Team model, but you call ProjectDetails. So here, self.pk is Teaminstance.pk.
What I do in the code i gave you is to call the get_absolute_url of the project instance.
But as told in the other answer, you should remove or change your get_absolute_url of your team model.
class Team(models.Model):
# ...
def get_absolute_url(self):
return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk})
^^^^^^^
Here, the wrong pk will be delived. Thx to #Bestasttung for clarification

Django: Change Choice selection from FK in a Form linked to an UpdateView

The Model flow Topic -> Section -> Article.
I am building an Update View for my FAQ project to update already created Articles. I want the Form to provide a selection of Sections based on the Topic the Article was created under. As I already have the Articles PK passed in through the URL I was hoping to use it to walk back up to the Topic when creating my filter. I am receiving an object has no attribute ‘section’ error when the template is attempting to render the form on line self.fields['section'].queryset = Section.objects.filter(topic_id=self.section.topic.id) in the UpdateAriticleForm. I need help to figure out my query filter.
The URL:
url(r'^ironfaq/article/update/(?P<pk>\d+)/$', ArticleUpdateView.as_view()),
The Form:
from django import forms
from .models import Topic, Section, Article
class CreateArticleForm(forms.ModelForm):
section = forms.ModelChoiceField(queryset=Section.objects.none())
def __init__(self, *args, **kwargs):
topic_pk = kwargs.pop('topic_pk')
super(CreateArticleForm, self).__init__(*args, **kwargs)
self.fields['section'].queryset = Section.objects.filter(topic_id=topic_pk)
class Meta:
model = Article
widgets = {
'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
}
fields = ('title','section','answer')
class UpdateArticleForm(forms.ModelForm):
section = forms.ModelChoiceField(queryset=Section.objects.none())
def __init__(self, *args, **kwargs):
super(UpdateArticleForm, self).__init__(*args, **kwargs)
self.fields['section'].queryset = Section.objects.filter(topic_id=self.section.topic.id)
class Meta:
model = Article
widgets = {
'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
}
fields = ('title','section','answer')
The View:
class ArticleUpdateView(UpdateView):
model = Article
form_class = UpdateArticleForm
template_name = "faq/form_create.html"
def form_valid(self, form):
article = form.save(commit=False)
article.activity_user = self.request.user.username
article.activity_date = datetime.datetime.now()
article.save()
self.success_url = "/ironfaq/%s/%s/%d" % (article.section.topic.slug,article.section.slug,article.id)
return super(ArticleUpdateView,self).form_valid(form)
The Models:
class Topic(Audit):
name = models.CharField(max_length=255)
icon = models.CharField(max_length=25,blank=True,null=True)
sort = models.SmallIntegerField()
slug = models.SlugField()
class Meta:
verbose_name_plural = "topics"
def __str__(self):
return self.name
class Section(Audit):
name = models.CharField(max_length=255)
sort = models.SmallIntegerField()
slug = models.SlugField()
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "sections"
def __str__(self):
return self.name
class Article(Audit):
title = models.CharField(max_length=255)
sort = models.SmallIntegerField()
slug = models.SlugField()
section = models.ForeignKey(Section,on_delete=models.CASCADE)
answer = models.TextField()
vote_up = models.IntegerField(default=0)
vote_down = models.IntegerField(default=0)
view_count = models.IntegerField(default=0)
class Meta:
verbose_name_plural = "articles"
def __str__(self):
return self.title
The answer to the this issue was not passing 'pk' as a argument to the form and to add get_form_kwargs to the view to enable the form to see the 'pk' passed in the URL.
Form:
class UpdateArticleForm(forms.ModelForm):
section = forms.ModelChoiceField(queryset=Article.objects.none())
def __init__(self, pk, *args, **kwargs):
super(UpdateArticleForm, self).__init__(*args, **kwargs)
self.fields['section'].queryset = Section.objects.filter(topic_id__exact=Article.objects.filter(id=pk).first().section.topic.id)
View:
class ArticleUpdateView(UpdateView):
model = Article
form_class = UpdateArticleForm
template_name = "faq/form_create.html"
def get_form_kwargs(self):
kwargs = super(ArticleUpdateView,self).get_form_kwargs()
kwargs.update(self.kwargs)
return kwargs
def form_valid(self, form):
article = form.save(commit=False)
article.activity_user = self.request.user.username
article.activity_date = datetime.datetime.now()
article.save()
self.success_url = "/ironfaq/%s/%s/%d" % (article.section.topic.slug,article.section.slug,article.id)
return super(ArticleUpdateView,self).form_valid(form)