0

I am not sure if I am using this Class based view correctly. What I am trying to do I thought was very simple. Basically is a form based on a model where I only use the 'User' field from:

class OnSiteLog(models.Model):
    objects = models.Manager()
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    checkIn = models.DateTimeField('checkin_date', null=True, blank=True)    
    checkOut = models.DateTimeField('checkout_date', null=True, blank=True)    
    notes = models.CharField(null=True, blank=True,max_length = 200)
    location = models.CharField(null=True, blank=True, max_length=200)
    autoCheckin = models.BooleanField(null=True, blank=True, default=False)


class QueryUser(LoginRequiredMixin, FormView):
    model = OnSiteLog
    form_class = QueryForm
    template_name = 'log/query.html'
    success_url = '/'
    def post(self, request, *args, **kwargs):

        theRecord = OnSiteLog.objects.filter(user_id=24)
        print(theRecord[0].user)
        super(QueryUser, self).post(request, *args, **kwargs)
        return render(request, 'log/query.html', {'log':theRecord})
    

From there: the template is pretty simple with a crispy form:

{% block content %}
   <div class="breadcrumb-area">


        <!-- Background Curve -->
        <div class="breadcrumb-bg-curve">
            <img src="{% static '/img/core-img/curve-5.png' %}" alt="">
        </div>
    </div>
<div class="container">
    <h2> Query for User </h2>
    <div class="row">
      <div class="col-sm">
            {% crispy form %}
      </div>
    </div>

    <div class="row">
       Logs
      <div class="col-sm">
      <table class="table">
      <tr>
        <th>User</th>
        <th>Check In</th>
        <th>Check Out</th>
        <th>Location</th>
        <th>Notes</th>
       
        </tr>
        {% for ins in log %}
          <tr>
            <td>{{ ins.user }}</td>
            <td>{{ ins.checkIn }}</td>
            <td>{{ ins.checkOut }}</td>
            <td>{{ ins.location }}</td>
            <td>{{ ins.notes }}</td>
            {% if request.user.is_superuser %}
              <td> <a href="{% url 'log_detail' ins.id %}"><button type="button" class="btn btn-primary">Edit Entry</button></td>
            {% endif %}

            <!-- td><a href="{{ ins.id }}"><button type="button" class="btn btn-primary">Edit Insurance</button></a></td>
            <td><button type="button" class="btn btn-danger">Delete Insurance</button></td> -->
          </tr>
        {% endfor %}
      </table>
           
      </div>
    </div>


</div>

{% endblock %}

What I want though, is to reload the form after they submit with a selected name, and the reloaded form to have all the log in information from OnSiteLog for that user (a select all where user = '...' basically)

I got a good ways there though I am not sure how to get the proper variable out of the request in the def post method, and then as a test I put id 24. So I am not sure how to get that variable out?

Secondly, crispy forms (I think) keeps giving me this error:

VariableDoesNotExist at /query_user/
Failed lookup for key [form] in [{'True': True, 'False': False, 'None': None}, {}, {}, {'log': <QuerySet [<OnSiteLog: OnSiteLog object (100)>, <OnSiteLog: OnSiteLog object (101)>, <OnSiteLog: OnSiteLog object (107)>, <OnSiteLog: OnSiteLog object (109)>, <OnSiteLog: OnSiteLog object (124)>, <OnSiteLog: OnSiteLog object (148)>, <OnSiteLog: OnSiteLog object (152)>, <OnSiteLog: OnSiteLog object (156)>, <OnSiteLog: OnSiteLog object (158)>, <OnSiteLog: OnSiteLog object (163)>, <OnSiteLog: OnSiteLog object (168)>, <OnSiteLog: OnSiteLog object (172)>, <OnSiteLog: OnSiteLog object (178)>, <OnSiteLog: OnSiteLog object (192)>, <OnSiteLog: OnSiteLog object (193)>, <OnSiteLog: OnSiteLog object (550)>, <OnSiteLog: OnSiteLog object (552)>, <OnSiteLog: OnSiteLog object (556)>, <OnSiteLog: OnSiteLog object (559)>, <OnSiteLog: OnSiteLog object (562)>, '...(remaining elements truncated)...']>}]

So in addition to not overly sure how I get the correct variable out in the def post I am also not sure why the rerendering of the form is freaking out.

Codejoy
  • 3,722
  • 13
  • 59
  • 99

1 Answers1

1

You could try instead to override these methods of the FormView, and take the user to the view again with the proper context to fill the form.

# get the id of the log that was just created

    def form_valid(self, form, *args, **kwargs):
        user = form.cleaned_data.get('user')
        self.log_id = User.objects.get(username=user).select_related('log').last().id
        return super().form_valid(form, *args, **kwargs) 

# redirect successful form to same view

    def get_success_url(self):
        return reverse('this-view', kwargs={'id': self.log_id})

# render populated form in context

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        try:
            context['form'] = self.form_class(instance=OnSiteLog.objects.get(id=self.kwargs['id']))
        except ObjectDoesNotExist:
            context['form'] = self.form_class()
        finally: 
            return context

Then you should be able to populate your form with the instance of OnSiteLog that you just created. However, with this you would have to have optional url paramaters in the url Django optional url parameters.

twrought
  • 636
  • 5
  • 9
  • I am going to try this when I get to a computer, although, the query.html file has a crispy_form which is just the 'user' , so there is no other form to populate as the idea was a list of all logs for a user which i was trying to handle via that for loop in the template. I think maybe it is an issue here that perhaps the class views expect all the data to be of a form? (in this case my form has one field) and doesn't allow for 'stacking' or tacking any extra data back to the template? – Codejoy Jan 26 '21 at 04:54
  • I actually got it ready by going to a second html file that ditches the crispy forma nd just does the for loop from the template, now if I just knew how to grab the result in the def post instead of hardcoding the ID id be golden – Codejoy Jan 26 '21 at 05:04
  • Yeah that sounds good - just another ListView listing the user's logs. From your form, redirect to that new view but add the new user's id or username in the url: ```def get_success_url(self): return reverse('new-view', kwargs={'id': user.id})```. Then you can use ```kwargs['id']``` in your next ```context``` or ```get_context_data```, depending if this is a CBV or FBV. ```logs = OnSiteLog.objects.filter(user__id=kwargs['id'])``` – twrought Jan 26 '21 at 05:06
  • oh man, I suck :D I did it in a hacky way. I cannot believe this little bit is giving me trouble, I clearly have never had to mix CBV or FBV much. Using tutorials and what not is great but doesn't show the nuts and bolts always about this stuff...I edited my original question and still not sure how I can get the returned userid but going by what you say, I don't use a def post in the CBV at all.... – Codejoy Jan 26 '21 at 05:14
  • Actually gave a gright answer here even though my hack (yes total hack) was going in a different direction. This is just a small covid tracking app for the office so it isn't some robust enterprise level, but your prompts did help. I got it with the code in my edit but for the .filter(user_id=request.POST.get('user')) worked greatish (pagination doesn't work this way, but the rest works fine). I might come back and refine this later. – Codejoy Jan 26 '21 at 06:30