Dynamic form generation
I have a model for event invitations:
class EventInvitation(models.Model):
from_user = models.ForeignKey(User, related_name="inviters")
to_user = models.ForeignKey(User, related_name="invited")
text = models.CharField(max_length= 150)
event = models.ForeignKey(Event)
sent = models.DateTimeField(auto_now=True)
status = models.IntegerField(choices=INVITATIO开发者_运维问答N_STATI, default=0)
What I am trying to accomplish is to have a dynamic invitation form (NOT ModelForm), where the inviter has a selection of users, based on a query / people who CAN be invited by that particular user, and a selection of groups, also based on a query (the inviter has to be the owner of the group)... Since the EventInvitation is for a single user, I would then iterate through the selected users AND members of the group and create individual invitations for all of them. Any idea how I could generate this dynamic form?
As I understand, you want a logged in user, from an event page, click on a "Invite Others" button, which shows him a form, where he can select specific users and groups, specify some text, and click on "Send". Then your app should create many instances of the invitation (one per user) and send them, tracking the status of invitation. If this is correct, here are my suggestions for implementing this:
Using the following models will give you more control over your data (keeping the text only once, and allowing you to look up all users for a specific invitation):
class EventInvitation(models.Model):
inviter = models.ForeignKey(User, related_name="inviters")
event = models.ForeignKey(Event)
text = models.CharField(max_length= 150)
created = models.DateTimeField(auto_now=True)
class EventInvitationInvitee(models.Model):
event_invitation = models.ForeignKey(EventInvitation)
user = models.ForeignKey(User, related_name="invited")
status = models.IntegerField(choices=INVITATION_STATI, default=0)
Use a simple form like this:
from django.contrib.auth.models import User, Group
class InviteForm(forms.Form):
text = forms.CharField(widget=forms.Textarea)
users = forms.ModelMultipleChoiceField(queryset=User.objects.all())
groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all())
def __init__(self, user, *args, **kwargs):
super(InviteForm, self).__init__(*args, **kwargs)
self.fields['users'].queryset = User.objects.filter( ... )
self.fields['groups'].queryset = User.objects.filter( ... )
Replace ...
with your code for filtering the correct groups and users.
And a view in this fashion:
def invite(request, event_id):
event = get_object_or_404(Event, pk=event_id) # you can check if your user is allowed to access this event here
if request.method == 'POST':
form = InviteForm(request.user, request.POST)
if form.is_valid():
invitation = EventInvitation.objects.create(inviter=request.user, event=event, text = form.cleaned_data['text'])
users = set()
for user in form.cleaned_data['users']:
users.add(user)
EventInvitationInvitee.objects.create(event_invitation=invitation, user=user)
for group in form.cleaned_data['groups']:
for user in group.user_set.all():
if user not in users:
users.add(user)
EventInvitationInvitee.objects.create(event_invitation=invitation, user=user)
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = InviteForm(request.user)
return render_to_response('invite.html', {'form': form})
Update: You can also create a dynamic form in a more pythonic way like this:
def get_invite_form(user):
class InviteForm(forms.Form):
text = forms.CharField(widget=forms.Textarea)
users = forms.ModelMultipleChoiceField(queryset= ... )
groups = forms.ModelMultipleChoiceField(queryset= ... )
return InviteForm
replacing ...
with a queryset using the user parameter, and later use get_invite_form(request.user)(request.POST)
and get_invite_form(request.user)()
instead of InviteForm()
.
精彩评论