Creating two different profiles in one application - python

I am building a BlogApp App and I have two different sections, One is Blog Section and another is Article Section.
AND i am trying to create two different profiles for them.
When a user register or signup then a Profile is successfully creating for Blog Section ( NOT Article section ). BUT i am trying to do :- When user click on Article section after signup then there will be option of creating another Profile for Article Section and both will be different profile. ( AND there will be no relation between Blog Profile and Article Profile BUT user will same )
Blog Profile is successfully creating BUT I am trying to make Article Profile.
models.py
class ArticleProfile(models.Model):
user = models.ForeignKey(User,default='',null=True,on_delete=models.CASCADE)
full_name = models.CharField(max_length=30,default='')
views.py
def create_profile(request):
if request.method == 'POST':
form = ArticleProfileForm(request.POST,request.FILES,instance=request.user)
if form.is_valid():
custom_form = form.save(False)
custom_form.save()
messages.success(request, "Article Profile is Created")
return redirect('dating:DatingSection')
else:
form = ArticleProfileForm(instance=request.user)
context = {'form':form}
return render(request, 'dating/create_profile.html', context)
BUT when i create profile using this form then it is not saving in Admin.
Any help would be Appreciated.
Thank You in Advance.

I think the problem is here:
form = ArticleProfileForm(request.POST,request.FILES,instance=request.user)
^^^^^^^^^^^^
You are passing User as instance where the ArticleProfileForm creates ArticleProfile instance. So you need to remove that part of the code. And update the code like this:
form = ArticleProfileForm(request.POST,request.FILES)
if form.is_valid():
custom_form = form.save(False)
custom_form.user = request.user # change here
custom_form.save()
If still the problem persists, try renderning the form errors to pin point what is exactly wrong here.

Related

How to bind a django form to an object instance

I come from DRF background so please already assume that I might be getting something wildly wrong here. I am trying to use Django Form as a sort of proxy for DRF serializers. As in, when I fetch an object, I can quickly render it back, and I can of course accept POST requests and store them. What I can't seem to find is how do I use my object instances to process them with forms.
Here's my form:
class ProfileForm(ModelForm):
class Meta:
model = UserProfile
fields = ('name', 'profile_pic')
The actual model:
class UserProfile(models.Model):
user = models.OneToOneField(CustomUser, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
profile_pic = models.ImageField(upload_to='profile_image', null=True, blank=True)
def __str__(self):
return str(self.user)
My view:
def get_profile(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
# update the model
profile = request.user.userprofile
form = ProfileForm(model_to_dict(profile))
if not form.is_valid():
form = ProfileForm()
return render(request, 'profile-edit.html', {'form':form})
else:
return render(request, 'index.html')
So, in my view (which is a GET view), I'm doing something like this:
from django.forms import model_to_dict
profile = request.user.userprofile
form = ProfileForm(model_to_dict(profile))
return render(..., form)
Is this even the right approach? Besides, the problem is that my form doesn't seem to handle the profile_pic field properly (i.e. the img src field in the from html is just __).
Ideally I would want to build the form from the object instance itself, but that also doesn't work.
form = ProfileForm(instance = profile) is bound, but not valid
form = ProfileForm(UserProfile.objects.all()[0]) is bound, and I can access data items through form.data.<fields>, but as soon as do form.is_valid(), I get:
AttributeError: 'UserProfile' object has no attribute 'get'
UPDATE: form = ProfileForm(request.<GET/POST>, instance=profile) is actually bound but not valid with the error that field name is required, even though profile.name is indeed valid CharField.
So how can I take my object, then bind it to a form, and then return it to be rendered properly. Imgine this is a user profile that I render, but also let the user update it whenever they want. What is the Django way of doing it? (I come from DRF background.)
Most of the SO answers that I have found almost always initialize the form with request.POST which I don't need.
EDIT: My use case, I have an endpoint /profile which, when requested as GET, should return a profile (with all the info that their UserProfile object holds but the user can also edit any of the fields that they want to. Say they have edited a field, they can simply hit update, which would then submit the form. On the backend, there profile would get updated, and they would get served the latest profile details. Of course, I can do it by rendering a from using a template, but I instead wanted to use the form which is already there. As I mentioned model_to_dict approach kind of serves this point to some extent, except it breaks for images... so I thought there might be a solution.
Looking at your view you make some mistakes which simply make using the forms difficult. Firstly if you want to update a form you should instantiate the form with the model instance so instead of form = ProfileForm(model_to_dict(profile)) it should be form = ProfileForm(instance=profile).
Also right after this line you write:
if not form.is_valid():
form = ProfileForm()
Why check is_valid on a form that is not bound?
Your view should ideally look something like:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def get_profile(request):
profile = request.user.userprofile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return redirect('some-view-name')
return render(request, 'profile-edit.html', {'form':form})

Save filled form data in Django if user is not logged in?

I search Django-way to do some non tipical feature (I think). My env is Django 2.0.2, PostgreSQL 9.6 and Python 3.6.4. So, I have model and form like:
# ./app/models.py
from users.models import User # custom user model
class SubscribeModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=80)
# ./app/forms.py
class SubscribeForm(forms.Form):
phone = forms.EmailField(label='Phone Number', max_length=100)
Also, my view for this model like:
# ./app/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from users.models import User
class SubscribeView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
template_name = 'app/subscribe.html'
form_class = SubscribeForm
def post(self, request):
user = get_object_or_404(User, id=request.user.id)
form = self.form_class(request.POST, instance=user)
if form.is_valid():
form.save()
return redirect('/')
return render(request, self.template_name, {'client': user, 'form': form})
Would be great to understand what to do that logic after save form:
Anonymous user fill the form and click Save;
He is redirecting to login page (because LoginRequiredMixin);
After enter to the site, all data which he filled — saved to his account (automatically).
This feature we can see when online shopping: we choose goods, add to
our cart and only later, site ask us for login to site, if we are not (for save our order).
I think, my question solve saving data to request.session and re-save to DB after logged in, but I have no idea how to do that on my code and is this correctly? I am newbie in Django... yet!
Actually using request.session to store the data without saving it to the database is one approach, you can eighter save it to the localStorage or sessionStorage if you are developing mainly javascript AJAX frontent. But if you render every view with django then is using request.session better for you. Consider storing ids of the objects in the request.session in array and then use it as you want, remember to seralize it to JSON (json.dumps(list of ids)) before assigning it to the request.session.

Django Admin - Custom Inline Form

I'm attempting to use a custom inline form within the django admin.
admin.py --
class EmpInline(admin.StackedInline):
model = Emp
form = UpdateYearlyForm
show_change_link = True
class CompanyAdmin(admin.ModelAdmin):
list_display = ('companyname','companyid','get_active', 'get_updated')
inlines = [EmpInline]
When the Company name is clicked on, the company details are shown along with a formset for all the related employees.
This works in regards to displaying the form however one of the fields is a custom choice field which indirectly updated a model field. Which, in the normal user view (this form needs to be used both by an admin for all records and for users for the records pertaining to them) the custom field is handled as below.
I've only shown a snippet of the view as it is quite long.
views.py --
if formset.is_valid():
for form in formset.forms:
if form.is_valid():
obj = form.save(commit=False)
data = form.cleaned_data
if data['updatefield'] == 'accident':
obj.years += 1
else data['updatefield'] == 'free':
obj.years += 1
obj.save()
Is there a way of handling the form (and the custom field) in the same way when used as an inlineform in the admin?
If it helps anyone - overriding the save() function on the form itself sorted this problem and it probably better practice therefore I changed to using this on both the User and Admin side.

Custom django form that has fields populated from database

I am new to Django. I have a custom form that uses forms.Modelform to create a custom form from my model. I have some data in my database already that I manually input for testing.
However, the user and course field shows up as dropdowns. But they do not have any data in the dropdown list. How can I have django to pull data from the database and display the information into each dropdown on my form?
models.py:
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
view.py:
def home(request):
if request.method == 'GET':
form = StudentForm()
else:
form = StudentForm(request.POST)
if form.is_valid():
pass
return render(request, "request.html", {'form': form}, context_instance=RequestContext(request))
forms.py:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
Update
Actually found out that the changes weren't saved to my DB. They are now loading into the form. However in the dropdown list, it is showing up as "Student Object", and "Course Object"
How can I make it so they show up with proper names?
I would advocate that you move away from doing this if this is testing, and instead follow the guidelines for testing as outlined in the django tutorials, i.e. it creates a fake database for you and you create Users and Courses via Users.objects.create(username=...)

Django 1.6: How to print the number of objects a user uploaded?

I'm looking to get the number of objects a user uploaded into the database. For example:
Let's say i have a model called "Link" (which adds a url with its title and description) into my models.py:
class Link(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=200)
link = models.URLField(max_length=200)
description = models.TextField()
With its form:
class UrlForm(ModelForm):
class Meta:
model = Link
And its view:
def linkurl(request):
form = UrlForm()
if request.method == 'POST':
form = UrlForm(data=request.POST, instance=Link())
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect("home")
else:
form = UrlForm()
return render(request, "addurl.html", {'form': form})
So, knowing that the user can add urls to my app, i'm looking to print the number of urls the user uploaded into my app. Is that actually possible?
Thank you, in advance.
Use filter and count:
# change request.user to user id or user instance you need
user_links_count = Link.objects.filter(user=request.user).count()
There are multiple ways to achieve this.
Use a query and pass it into your template:
ndpu has already pointed it out here:
https://stackoverflow.com/a/22288960/659900
user_links_count = Link.objects.filter(user=request.user).count()
render(request, "addurl.html", {'form': form, linkscount: user_links_count})
Use a model property which you can use to access your model over the form directly, without touching the render method in your view.
add the following method to your link model: (warning: untested!)
#property
def user_links_count(self):
try:
return self.objects.filter(user=self.user).count()
except:
return 0 #or any error message you want
now in your template, you can access your link model directly via the form you are using. assuming you are not using an empty model:
{{ form._meta.model.user_links_count }}
However I would recommend ndpu's solution for a one off solution. Consider an enhancement to your model if you need this functionality more often

Categories

Resources