Django Dynamic Forms ManyToManyField - django

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.

Related

Creating a multiplechoice field using many to many relationship

Im trying to add a field called, interested_fields inside my personalInfo model which users can choose from and the choices themselves come from another models' objects with the help of ManyToMany relation between the two models. Here are my models.py codes(I simplified my personal model by removing some other fields like name, age, etc in order to make it more readable for you):
class Field(models.Model):
id = models.AutoField(primary_key=True)
slug = models.CharField(max_length=16, default='default')
title = CharField(max_length=32)
class PersonalInfo(models.Model):
id = models.AutoField(primary_key=True)
interested_fields = models.ManyToManyField(Field, blank=True)
then, I created a ModelForm like this:
class InterestedFieldsForm(forms.ModelForm):
interested_fields = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=Field.objects.all(), required=False)
class Meta:
model = PersonalInfo
fields = ['interested_fields']
and created a get and post functions inside my views like this:
class PersonalView(View):
template_name = 'reg/personal.html'
def get(self, request, *args, **kwargs):
context = {}
context['fields'] = Field.objects.all()
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
user = request.user
if request.method == 'POST':
form = InterestedFieldsForm(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
else:
form = InterestedFieldsForm()
return render(request, 'reg/done.html', context={'form': form})
and finally in template, inside the form I added this for loop:
{% for field in fields %}
<label class="containerq ant-col ant-col-md-6 ant-col-xs-8" >
<span>
<input type="checkbox" name="interested_fields" {% if field.slug in user.personalInfo.interested_fields %} checked="checked" {% endif %} value="{{field.title}}">
<span style="margin-left:7px" class="checkmark"></span>
</span>
<span>{{field.title}}</span>
</label>
{% endfor %}
when I submit the form it gives me this error:
cannot unpack non-iterable Field object
Im new to django so I really dont know what am I doing wrong. thank you for your answers
You should use a ModelMultipleChoiceField
interested_fields = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Field.objects.all(), required=False).

How to list only active users in dropdown menu

I want to list all active users in dropdown list. But all users are listed in the dropdown
How can I do it?
template
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="hidden" name="customer_id" value="{{ customer.id }}">
<button type="submit" class="btn btn-primary btn-sm">Assign</button>
</form>
forms
class AssignForm(forms.ModelForm):
class Meta:
model = Customer
fields = ('user',)
views
form = AssignForm(request.POST or None)
if request.POST:
customer_id = request.POST.get('customer_id', None)
customer = Customer.objects.get(id=customer_id)
user = UserProfile.objects.get(id=request.POST.get('user', None))
customer.user = user
customer.save()
# form.save()
return redirect('user:customer_list')
models
class UserProfile(AbstractUser, UserMixin):
company = models.ForeignKey(CompanyProfile, on_delete=models.CASCADE, null=True, unique=False)
username = models.CharField(max_length=500, unique=True)
first_name = models.CharField(max_length=200)
...
You can filter the user field in the assignForm with:
class AssignForm(forms.ModelForm):
user = forms.ModelChoiceField(
queryset=UserProfile.objects.filter(is_active=True)
)
class Meta:
model = Customer
fields = ('user',)
You can also filter this already at the model level with:
class Customer(models.Model):
user = models.OneToOneField(
'UserProfile',
limit_choices_to={'is_active': True}
)
In that case you do not need to specify this in the ModelForm(s).
I would strongly advise that you use the form in a POST request to create an instance, so:
customer_id = request.POST.get('customer_id')
if customer_id:
instance = get_object_or_404(Customer, id=customer_id)
else:
instance = None
if request.method == 'POST':
form = AssignForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return redirect('user:customer_list')
# …
You can create a new model ActiveUser and impose a filter to it (see https://www.django-rest-framework.org/api-guide/filtering/), depending on what "active" means in your case.

How to query a user's display information in the AccountDisplayInformation from the AccountModel

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)

Django Error: user_register_model matching query does not exist

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.

Django - ManyToManyField does not let me save, "This field is required" even though I select something

I have a formset like so:
class TransactionForm(ModelForm):
def __init__(self, *args, **kwargs):
try:
user = kwargs.pop("user")
except KeyError:
user = None
super(TransactionForm, self).__init__(*args, **kwargs)
self.fields["date"].widget.attrs["class"] = "datepicker"
if user is not None:
self.fields["categories"].queryset = Category.objects.get_all(user)
self.fields["account"].queryset = Account.objects.for_user(user)
class Meta:
model = Transaction
exclude = [""]
TransactionFormSet = modelformset_factory(Transaction, form=TransactionForm, exclude=("",))
View:
def transaction_create_view(request, account_id=None):
if request.method == "POST":
formset = TransactionFormSet(request.POST)
print(formset.errors)
if formset.is_valid():
for form in formset:
if form.is_valid and form.has_changed():
form.save()
if account_id is not None:
transactions = TransactionFormSet(queryset=Transaction.objects.for_account(account_id, request.user))
else:
transactions = TransactionFormSet(queryset=Transaction.objects.for_user(request.user))
transactions.form = curry(TransactionForm, user=request.user)
transactions.forms.insert(0, transactions.forms[-1])
del transactions.forms[-1]
context = {"transactions":transactions,}
return render(request, "transactions/transactions.html", context)
Model:
class Transaction(models.Model):
account = models.ForeignKey(Account)
date = models.DateField()
payee = models.CharField(max_length = 100)
categories = models.ManyToManyField(Category)
comment = models.CharField(max_length = 1000)
outflow = models.DecimalField(max_digits=10, decimal_places=3)
inflow = models.DecimalField(max_digits=10, decimal_places=3)
cleared = models.BooleanField()
class Category(models.Model):
title = models.CharField(max_length = 100)
subcategory = models.ForeignKey("self", blank=True, null=True)
user = models.ForeignKey(User)
budget = models.DecimalField(max_digits=10, decimal_places=2)
And template:
<form action="{% url 'transaction_create' %}" method="post">
{% csrf_token %}
{{ transactions.management_form }}
{% for form in transactions %}
{{ form.as_p }}
<input type="submit" value="Save transaction" />
<hr>
{% endfor %}
</form>
I input information in the empty form it produces and click on the save button, but the formset is not valid and I get this when I print the errors:
[{'categories': ['This field is required.']}, {}]
The categories in the template are represented by a <select>, where I select a category (the background is colored). Apparently it is not set though and thus I can't save, why is that? How can I fix it?
EDIT:
I have no idea why but now it works.
I reset the database re-created some data to see if that fixes things, and it did, I didn't change anything in the code.
If you override the save() in TransactionForm, you have to call save_m2m() to save the m2m objects.
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/