I'm working on my first Django project and employing django-registration and django-profiles. The former worked beautifully with nary an issue. The second has been a bit more problematic.
After many hours, specific user profiles can finally be viewed, which is terrific, along with a list of all profiles.
The two issues I'm encountering: django-profiles will not automatically create a new profile when a new user is created. Once a user is created in the admin, a profile should be created. That isn't occurring.
In addition, the profiles/edit_profile form results in this error:
"TemplateSyntaxError at /profiles/edit/ Caught NoReverseMatch while rendering: Reverse for 'edit_profile' with arguments '(,)' and keyword arguments '{}' not found."
I've searched for answers to these issues to no avail.
This is the model for the profile in my app file:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=35)
email = models.EmailField()
birth_date = models.DateField(blank=True, null=True)
city = models.CharField(max_length=25)
state = models.CharField(max_length=20)
zip_code = models.CharField(max_length=10)
def __unicode__(self):
return " %s" % (self.user)
def get_absolute_url(self):
return ('profiles_profile_detail', (), { 'username': self.user.username })
get_absolute_url = models.permalink(get_absolute_url)
This is my form:
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
This is the template:
{% extends 'base.html' %}
{% block page_title %}Edit Profile{% endblock %}
{% block headline %}Edit Stentorian Profile{% endblock %}
{% block content %}
<form action="{% url edit_profile user %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Interested in learning what errors I made and how to fix these. (I realize the user object carries first and last name, but there appears no other way to insert these into the profile other than with their own specific fields).
Any insight appreciated.
Edit: It seems to have worked out thanks to The Missing Manual. Unfortunately, /profiles/edit now bounces to /profiles/create. Not sure of this issue.
Here is a link to help you with this.
django-profiles the missing manual
Scroll down to NO MISSING PROFILES! section. Here they explain that to create a profile must be done with a signal whenever a User instance is created.
Related
I'm trying to make a favorite functionality where an user can add other users as their favorites.
In the View where the profile of an user is shown I have a button that adds an user or removes it if it was already added.
The problem is that I can't pass to the views the user that will be added as a favorite.
models.py
class User(AbstractUser):
is_type1 = models.BooleanField(default=False)
...
class Type1(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
favorite = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, related_name='favorite')
views.py
def FavoriteView(request, pk):
current_user = request.user
Type1.user = current_user.id
buser = Type1.user
Type1.favorite = get_object_or_404(User, id=request.POST.get('username')) # The of the error where I try to add the user being added as a favorite
fuser = Type1.favorite
if Type1.favorite.filter(id=request.user.id).exists():
Type1.favorite.remove(request.user)
else:
Type1.favorite.add(request.user)
return HttpResponseRedirect(reverse('profile-details', kwargs={'username': Type1.favorite}))
class UserView(DetailView):
model = User
...
template_name = 'users/profile-details.html'
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
favorite_connected = get_object_or_404(Type1.favorite, id=self.kwargs['username']) # The of the error where I try to add the user being added as a favorite
favorite = False
if favorite_connected.favorite.filter(id=self.request.user.id).exists():
liked = True
data['user_is_favorite'] = favorite
return data
profile-details.html
...
{% if user.is_authenticated %}
<form action="{% url 'favorite' object.id %}" method="POST">
{% csrf_token %}
{% if user_is_favorite %}
<button type="submit" name="favorite" value="{{object.id}}">Not favorite</button>
{% else %}
<button type="submit" name="favorite" value="{{object.id}}">Favorite</button>
{% endif %}
</form>
{% else %}
Log in to add user to favorites.<br>
{% endif %}
urls.py
path('profile/<str:username>/', UserView.as_view(), name='profile-details'),
path('favorite/<str:username>/', FavoriteView, name="favorite"),
One immediate problem I see is that your URL path wants a string for the username, but your URL for the form gives it the ID of the user, so that'll be an int.
In terms of your error, you're trying to pass a username, but I don't think that'll be in the POST data. However if it was, you should be able to do;
get_object_or_404(User, username=request.POST.get('username'))
However, based on my initial comment, you should probably just get the user by ID like you are doing, but use the PK of the user which is comes with your view;
get_object_or_404(User, id=pk)
You may also come across more errors, because you're assigning an object, if it exists to Type1.favorite and then attempting to do Type1.favorite.filter( which will fail. You can only .filter() on a queryset, not a model instance.
i'm currently working on a project that would have a database of reports of a scam. In the report section of the website I have a form, but I want anyone to be able to add multiple profiles with a click of a button. For example:
Nickname field: xyz
Steam profile: x
[ + ] <- button for adding more profiles, which when pressed would look something like this:
Nickname field: xyz
Steam profile: x
Steam profile 2: y [ Delete ]
[ + ]
I was looking into FormSets and Inline Formsets, but nothing turned up that would match this specific need, aswell as did not answer the question regarding storing the results of the form.
How would I go about creating the form for this?
How would I store the multiple results of Steam profile to my object that has a steam_profile = models.CharField?
My current model:
class Scammer(models.Model):
#Basic information for display
steam_id_64 = models.CharField(max_length=17, default='00000000000000000')
nickname = models.CharField(max_length=64, default='Nickname')
steam_profile = models.CharField(max_length=512, default='https://www.steamcommunity.com')
description = models.TextField(default='')
proof = models.TextField(default='')
#Date created var for ordering
date_created = models.DateTimeField(default=timezone.now, blank=True)
def __str__(self):
return self.nickname
def get_absolute_url(self):
return reverse('dashboard-home')
My view:
class ScammerCreateView(CreateView):
model = Scammer_Unapproved
template_name='dashboard/report.html'
fields = ['nickname', 'steam_id_64', 'steam_profile', 'description', 'proof']
My template:
{% block content %}
<div class="report-scammer">
<form method="POST">
{% csrf_token %}
<fieldset>
<legend>Report a scammer</legend>
{{ form|crispy }}
</fieldset>
<div>
<button type="submit">Report</button>
</div>
</form>
</div>
{% endblock content %}
Have the profiles as the Builtin Django User model or maintain a separate model with a link to the inbuilt User model. Now the scam report form can have the option to be linked to Multiple User accounts by using ManytoMany relationship field. check the below official documentation page,
[https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/][1]
I am adding a like functionality in my website where users can like each others posts.
I have done this successfully, however have one issue. This is checking whether the user has already liked the post, which has to be performed specifically in my HOME view.
This is so I can render my home page. To encounter this issue, I perform a .annotate() on my posts when retrieving them, and see if a user has liked a post.
I then pass this onto my home template and check if the user exists within the posts likes property.
Here's the related code.
models.py:
class Post(models.Model):
file = models.ImageField(upload_to='images/')
summary = models.TextField(max_length=600)
pub_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(User, through='Like', related_name='likes')
def __str__(self):
return self.user.username
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def summary_pretty(self):
return self.summary[:50]
#property
def total_likes(self):
return self.likes.count()
class Like(models.Model):
status = models.BooleanField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
views.py:
def home(request):
posts = Post.objects.all()
liked_or_not = Post.objects.annotate(likes__user=request.user)
return render(request, 'posts/home.html', {'posts': posts, 'liked_or_not': liked_or_not})
home.html:
{% if liked_or_not == True %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Unlike {{ post.total_likes }} </button>
{% else %}
<button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Like {{ post.total_likes }} </button>
{% endif %}
<form id="likepost{{ post.id }}" method="POST" action="{% url 'likepost' post.id %}">
{% csrf_token%}
<input type="hidden">
</form>
For those coming here for other possibilities in debugging the error message, I had made a mistake and entered in a query analogous to
Like.objects.filter(user=request.user).values('status', flat=True)
# instead of the correct
Like.objects.filter(user=request.user).values_list('status', flat=True)
I don't quite understand what do you want to do. If you want to check if the user liked at least one post, you can do it like this:
liked_or_not = Like.objects.filter(user=request.user).exists
If you want to check if a user liked a specific post, you can dot it like this:
liked_or_not = Likes.objects.filter(post_id=post_id, user=request.user).exists()
annotate has a different purpose. It annotates each object in the QuerySet with the provided list of query expressions. An expression may be a simple value, a reference to a field on the model (or any related models), or an aggregate expression (averages, sums, etc.) that has been computed over the objects that are related to the objects in the QuerySet. read more here https://docs.djangoproject.com/en/2.2/ref/models/querysets/#annotate
I encounterd similar problem and solved using .annotate
and below is my definition of Like in models.py
class Like(models.Model):
user = models.ForeignKey(
"users.User", on_delete=models.CASCADE, related_name="likes"
)
writing = models.ForeignKey(
"writings.Writing", on_delete=models.CASCADE, related_name="likes"
)
in views.py
filter_kwargs = {}
filter_kwargs["writing"] = OuterRef("pk")
filter_kwargs["user"] = request_user
subquery = Like.objects.filter(**filter_kwargs)
writing = (
Writing.objects.annotate(user_likes=Exists(subquery))
.get(id=id)
)
I'm trying to display specific content/data based on a logged in user. I want to display only their info. This is what I've tried but I can't get it to work.
views.py
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get(self, request):
demos = Demographics.objects.filter(user=request.user)
context = {
'demos': demos,
}
return render(request, self.template_name, context)
models.py
class Demographics(models.Model):
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, null=True)
last_name = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True)
HTML
{% if demos %}
{% for demographics in demos %}
<p>First Name</p> {{ demographics.first_name }}
{% endfor %}
{% else %}
<h3>you dont have demo yet</h3>
{% endif %}
I feel like I'm close. What am I missing?
I think the issue may be that you are filtering out all answers from your queryset because the content of request.user is not quite a match for a 'user' object. I don't know why they wouldn't match, but in my code I use:
User.objects.get(username = request.user.username)
I think debugging using pdb will help why the get is not rendering the data properly but if you know how django templateview class handles the context data, you have to modify the code a bit. Here I used get_context_data instead of get and hope this time it will work.
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get_context_data(self, **kwargs):
context = super(DemoView, self).get_context_data(**kwargs)
demos = Demographics.objects.filter(user=self.request.user)
context['demos'] = demos
return context
Also you can check if the table Demographics has the data for the selected user.
full Answer:
Views.py
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get(self, request, *args, **kwargs):
demos = Demographics.objects.filter(user=User.objects.get (username=request.user))
context = {
'demos': demos,
}
return render(request, self.template_name, context)
HTML:
{% if demos %}
{% for demographics in demos %}
<p>First Name</p> {{ demographics.first_name }}
{% endfor %}
{% else %}
<h3>you dont have demo yet</h3>
{% endif %}
urls.py
url(r'^test/', views.DemoView.as_view()),
admin.py
admin.site.register(Demographics)
models.py
class Demographics(models.Model):
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, null=True)
last_name = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True)
Go to django admin, check your objects, and make sure you're logged in to the account that has demographic objects associated with it.
The above setup works for me, if it doesn't work for you, you're most likely logged in as a user which doesn't have any demographic objects associated with it.
Also, don't name your models as plural, it should be Demographic, because it is a representation of one object. When you filter in views, you name the variable demographics (plural), because the query returns more than one object.
I have two models, the second one have a ForeignKeyto the first one.
I'm using Django form wizzard to complet many regrouped fields in separated steps. The problem is when I arrive in the "TeamMember" step, where I'm supposed to let the user enter many members.
I was thinking to use Django Inline formset, but I can not implement it inside my formwizard, I get a
[u'ManagementForm data is missing or has been tampered with']
error when I try to display this step.
Here is my implementation, if some one have any idea, it would be really appreciated :).
Don't hesitate to contact me if you need more informations.
Thanks in advance for your help.
Yann
models.py
class Team(models.Model):
name = name = models.CharField(_(u'Team'), max_length=50))
class TeamMember(models.Model):
team = models.ForeignKey(Team)
first_name = models.CharField(_('First name'), max_length=50, blank=True, null=True)
first_name = models.CharField(_(u'Last name'), max_length=50, blank=True, null=True)
forms.py
class FundingRequestFormTeam(ModelForm):
class Meta:
model = TeamMember
exclude = ('team',)
fields = ('first_name', 'last_name')
TeamMemberFormSet = inlineformset_factory(Team, TeamMember)
urls.py
team_wizard = TeamWizard.as_view(FORMS_DATA, url_name='team_data_step')
urlpatterns = patterns('lending.views',
url(r'^file/(?P<step>.+)/(?P<project_id>[0-9\-]+)$', login_required(team_wizard), name='team_step_edit'),
)
views.py
FORMS_DATA = [("info", TeamFormInfo),
("team_members", TeamFormSet),
("social", FundingRequestFormSocial),
("documents", FundingRequestFormDocuments), ]
The rest of the view is something simple like in the documentation of the django form wizard
team_step_teammembers.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% bootstrap_form form %}
{% endfor %}
{% else %}
{% bootstrap_form wizard.form %}
{% endif %}
</form>
Django version 1.7.3
Python version 2.7.5