I want to build a view that allows the user to update his profile picture.
Now in my view the cleaned data returns the current profile image path which then overwrites the existing one one by one. I'm not sure where the issue is.
Also since I use a default image within the model manager, I only want to delete the current imagefield if it isn't the default one.
# View
#require_POST
def update_profile_image(request, username):
"""
Updates the user profile
"""
form = ImageUpdateForm(request.POST)
if form.is_valid():
image = form.cleaned_data['profile_image']
print('image ' + str(image))
user = Account.objects.get(username=request.user.username)
user.profile_image = image
user.save()
return redirect('pollboard')
# Model
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=40, unique=True)
profile_image = models.ImageField(max_length=255, upload_to=get_profile_image_filepath, null=True, blank=True, default=get_default_profile_image())
# Custom Manager
class MyAccountManager(BaseUserManager):
def get_profile_image_filepath(self, filename):
return f'profile_image/{self.pk}/{"profile_image.png"}'
def get_default_profile_image():
return "profile_image/Logo_large.png"
# Form
class ImageUpdateForm(forms.ModelForm):
class Meta:
model = Account
fields = ['profile_image']
# Template
<div class="profile-image-modal">
<form method="post" action="update_profile_image/">
{% csrf_token %}
{{ profile_image_form }}
<button type="submit">Save Image</button>
</form>
</div>
You need to pass both request.POST and request.FILES to the form:
#require_POST
def update_profile_image(request, username):
"""
Updates the user profile
"""
# pass request.FILES as well ↓
form = ImageUpdateForm(request.POST, request.FILES)
if form.is_valid():
image = form.cleaned_data['profile_image']
print('image ' + str(image))
user = Account.objects.get(username=request.user.username)
user.profile_image = image
user.save()
return redirect('pollboard')
furthermore you should set the encytpe=… [dev-mozilla] of the form to multipart/form-data to encode the file:
<form method="post" enctype="multipart/form-data" action="update_profile_image/">
{% csrf_token %}
{{ profile_image_form }}
<button type="submit">Save Image</button>
</form>
Related
Account is my AUTH_USER_MODEL and AccountDisplayInfo consists of all the additional display info of every account. So they can input and submit, and subsequently update their information. These are my codes, but I'm unsure why it isn't working. First of all, I am receiving this error:
DoesNotExist at /account/5/displayinfo/ AccountDisplayInfo matching query does not exist.
Secondly, the "update" function isn't working.
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
class AccountDisplayInfo(models.Model):
account = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
instagram = models.CharField(max_length=50, unique=True, blank=True, null=True) #instagram
.html
<form method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-primary btn-sm col-lg-5">Update</button>
</div>
</form>
views.py
def display_information_view(request, *args, **kwargs):
user_id = kwargs.get("user_id")
account = Account.objects.get(pk=user_id)
context = {}
displayinfo = AccountDisplayInfo.objects.get(account=account)
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
info.save()
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
return redirect("account:view", user_id=account.pk)
else:
form = DisplayInformationForm(request.POST, instance=request.user,
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
else:
form = DisplayInformationForm(
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
return render(request, "account/displayinfo.html", context)
forms.py
class DisplayInformationForm(forms.ModelForm):
class Meta:
model = AccountDisplayInfo
fields = ('instagram')
Also, would be great if you can advise on this::
If I have 2 tables. Table 1 and Table 2. Table 2 has a foreign key to table 1 but table 1 dont have a foreign key to table 2. How can I query table 2's data from table 1? Thanks
By default .get() will return a DoesNotExist exception if no object matches the query you executed and stop the code from running, so if you want to input it manually on the same page use filter instead:
displayinfo = AccountDisplayInfo.objects.filter(account=account).first()
Then in your template do something like this:
{% if displayinfo %}
... show display info...
{% else %}
<p> No info yet </p> <!-- (or show some form) -->
{% endif %}
To answer your other question:
You have to use the related_name or related models attribute to access the ForeignKey data or use the model name with the _set suffix, for example:
class Post(models.Model):
title = models.CharField(max_lenght=10)
class Comment(models.Model):
body = models.CharField(max_lenght=200)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
then you would get the Post and its comments:
post = Post.objects.get(pk=1)
comments = post.comments.all()
if you didn't have the related_name attribute in your model field you would do this instead:
comments = post.comment_set.all()
UPDATE
Maybe the issue is in your Form class, try removing the save method from it and instead do this in your view:
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
info.save()
return redirect("account:view", user_id=account.pk)
With these codes, I want each user to be able to upload their own file in their own model
forms.py:
class sp_UserNewOrderForm(forms.Form):
file= forms.FileField()
models.py:
class sp_Order(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.owner.username
class sp_OrderDetail(models.Model):
order = models.ForeignKey(sp_Order, on_delete=models.CASCADE)
file= models.FileField()
def __str__(self):
return self.order.owner.username
views.py:
#login_required
def add_user_order(request):
new_order_form = sp_UserNewOrderForm(request.POST or None)
if new_order_form.is_valid():
order = sp_Order.objects.filter(owner_id=request.user.id).first()
if order is None:
order = sp_Order.objects.create(owner_id=request.user.id)
file= new_order_form.cleaned_data.get('file')
order.sp_orderdetail_set.create(file=file)
# todo: redirect user to user panel
# return redirect('/user/orders')
return redirect('/')
return redirect('/')
HTML:
<form method="post" action="/add_sp">
{% csrf_token %}
{{ form.count }}
<button type="submit" class="btn btn-primary container">
upload
</button>
</form>
But these codes do not create the model. what is the problem?
The problem appears to be in this line:
order = sp_Order.objects.filter(owner_id=request.user.id).first()
I think you should replace owner_id = request.user.id with owner = request.user
owner_id is not an attribute of the model you're trying to filter or create
You need to include request.FILES when instantiating the form for the POST request.
def add_user_order(request):
if request.method == 'POST':
new_order_form = sp_UserNewOrderForm(request.POST, request.FILES)
if new_order_form.is_valid():
order = sp_Order.objects.filter(owner_id=request.user.id).first()
if order is None:
order = sp_Order.objects.create(owner_id=request.user.id)
file= new_order_form.cleaned_data.get('file')
order.sp_orderdetail_set.create(file=file)
# todo: redirect user to user panel
# return redirect('/user/orders')
return redirect('/')
I am making a twitter clone app in Django. I have a model, and a modelform as so:
Class Tweet(models.Model):
content = models.TextField(blank=True, null=True)
image = models.FileField(upload_to='images/', blank=True, null=True)
class TweetForm(forms.ModelForm):
class Meta:
model = Tweet
fields = ['content',]
def clean_content(self):
content = self.cleaned_data.get('content')
if len(content) > MAX_TWEET_LENGTH:
raise forms.ValidationError('This tweet is too long')
I have a view for this:
def tweet_create_view(request, *args, **kwargs):
if request.method == 'POST':
form = TweetForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
form = TweetForm()
context = {
'form': form
}
return render(request, 'components/form.html', context)
and the template:
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-secondary" type="submit">Save</button>
</form>
When I submit the form data, in the database the value is shown as NULL, even if I pass in some text. What am I doing wrong??
You are not returning the cleaned form data from the clean function, as your clean function doesn't return anything if it passes the validation, it saves None/Null to DB.
def clean_content(self):
content = self.cleaned_data.get('content')
if len(content) > MAX_TWEET_LENGTH:
raise forms.ValidationError('This tweet is too long')
return content
How to fix This Error I'm Trying To Fix This Error But I Get Again And Again
i want to detect user who fill the form for example test fill the form but when i write the code down below i get this error
Any Help Will Be Appreciated!
ERROR
user_register_model matching query does not exist.
ERROR SCREENSHOT
Here is my Views.py
def buy_form(request):
if request.method == 'POST':
usr_buy = user_buy_form(request.POST)
if usr_buy.is_valid():
usr_buys = usr_buy.save(commit=False)
user_register_obj = user_register_model.objects.get(user=request.user)
usr_buys.users = user_register_obj
usr_buys.save()
else:
return print(usr_buy.errors)
else:
usr_buy = user_buy_form()
context = {'usr_buy':usr_buy}
return render(request,'user_buy.html',context)
Here is my Models.py
class user_register_model(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
join_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.user.username
class user_buy(models.Model):
users = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=200)
payment_method = models.CharField(max_length=500)
price = models.IntegerField()
Trade_limits = models.IntegerField()
Location = models.CharField(max_length=1000)
def __str__(self):
return self.users.user.username
Here is my Forms.py
class user_buy_form(forms.ModelForm):
class Meta():
model = user_buy
fields = '__all__'
exclude = ('users',)
Here is my user_buy.html
{% extends 'base.html' %}
{% block body_block %}
<form class="form-control" method="POST">
{% csrf_token %}
{{usr_buy.as_p}}
<input type="submit" class="btn btn-primary" value="Submit">
</form>
{% endblock %}
I didn't see any points here to create the user_register_model.If you are trying to add the currently logged in user you can do this:
request.user will give you the currently logged in user so for this the user must be logged in.
#login_required
def buy_form(request):
if request.method == 'POST':
usr_buy = user_buy_form(request.POST)
if usr_buy.is_valid():
usr_buys = usr_buy.save(commit=False)
usr_buys.users = request.user
usr_buys.save()
return redirect('some_path') # redirect to some path after saving the form
Class names should normally use the CapWords convention.
I think the request.user is not present in the user_register_model model thats why it is giving matching query doesnot exist error, first create it in the user_register_model and then query it.
I have a problem that I want to make a football league page that can submit the starting XI list.
But I don't know how to build the Dynamic Form.
User (which is the team owner) can Login to choose the match to upload the starting XI.
Website will show up the player list of the Team and let the User select Max of 11 and submit.
The important thing is
How can I generate the form with the Players belongs to Team.
How to let the User upload Home / Away (The team belongs to User) starting XI only.
Model.py
class Schedule(models.Model):
schedule_name = models.CharField(max_length=7, choices=LEAGUE_CHOICES, default='nil')
schedule_home = models.ForeignKey(Team, on_delete=models.CASCADE,default='',related_name='schedule_home')
schedule_away = models.ForeignKey(Team, on_delete=models.CASCADE,default='',related_name='schedule_away')
class Player(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
player_name = models.CharField('Player Name', max_length=30, unique=True)
player_team = models.ForeignKey(Team ,on_delete=models.SET_DEFAULT, default=1)
class Team(models.Model):
team_name = models.CharField('Team Name', max_length=30, unique=True)
team_owner = models.OneToOneField(User,on_delete=models.CASCADE,related_name='owner')
class Match_Starting(models.Model):
starting_schedule = models.OneToOneField(Schedule,on_delete=models.CASCADE)
home_starting = models.ManyToManyField(Player,blank=True,related_name='home_starting')
away_starting = models.ManyToManyField(Player,blank=True,related_name='away_starting')
#receiver(post_save, sender=Schedule)
def create_match_stat(sender, instance, created, **kwargs):
if created:
Match_Starting.objects.create(starting_schedule=instance)
Forms.py
class MatchStartingForm(forms.ModelForm):
class Meta:
model = Match_Starting
fields = '__all__'
Views.py
#login_required
def update_starting(request):
if request.user.is_authenticated:
try:
selected_team = Team.objects.get(team_owner=request.user)
except:
return HttpResponseRedirect('/')
if request.method == 'GET':
selected_player = Player.objects.filter(player_team=selected_team).order_by('player_name')
team_schedule_list = Schedule.objects.filter(schedule_time__lte=datetime.datetime.now() + datetime.timedelta(weeks=1),schedule_time__gte=datetime.datetime.now() + datetime.timedelta(minutes=30)).filter(Q(schedule_home__team_name=selected_team)|Q(schedule_away__team_name=selected_team))
return render(request, 'update_starting/update_starting.html',{"user":request.user,"team":selected_team,"player":selected_player,"schedule":team_schedule_list})
if request.method == 'POST':
selected_match= get_object_or_404(Match_Starting, starting_schedule__id=request.POST.get("schedule_id"))
request.POST = request.POST.copy()
if selected_team == selected_match.starting_schedule.schedule_home:
request.POST['home_starting'] = request.POST['starting']
form = MatchStartingForm(request.POST, instance=selected_match)
if form.is_valid():
selected_match = form.save(commit=False)
selected_match.save()
form.save_m2m()
elif selected_team == selected_match.starting_schedule.schedule_away:
request.POST['away_starting'] = request.POST['starting']
form = MatchStartingForm(request.POST, instance=selected_match)
if form.is_valid():
selected_match = form.save(commit=False)
selected_match.save()
form.save_m2m()
return HttpResponseRedirect('/')
update_starting.html
<div>
<form action="" method="post">
{% csrf_token %}
<select name="schedule_id">
{% for x in schedule %}
<option value="{{x.id}}">{{x.get_schedule_name_display}} {{x.schedule_home}} - {{x.schedule_away}}</option>
{% endfor %}
</select>
{% for x in player %}
<input type="checkbox" name="starting" value="{{x.id}}">{{x.player_name}}<br>
{% endfor %}
<input type="submit" class="button" value="Save">
</form>
</div>
How can I generate the form with the Players belongs to Team.
You first would need a form for players:
class PlayerForm(forms.ModelForm):
class Meta:
model = Player
fields = '__all__'
and then put this into practice: Django Formsets
How to let the User upload Home / Away (The team belongs to User) starting XI only.
You will need here a form too, this time for the Schedule model as well.
#rchurch4 said: They just want to know how to ensure that the User can only upload the roster for his team.
If that the case, you only have to be sure in your Team list view you only list teams belonging to the authenticated User.