Skip to content

Bugfix delete button doesn't work for project#160

Merged
kbeker merged 2 commits intomasterfrom
bugfix-delete-button-doesnt-work-for-project
May 6, 2019
Merged

Bugfix delete button doesn't work for project#160
kbeker merged 2 commits intomasterfrom
bugfix-delete-button-doesnt-work-for-project

Conversation

@maciejSamerdak
Copy link
Collaborator

@maciejSamerdak maciejSamerdak commented Apr 26, 2019

Fixes acknowledged issues regarding project deletion feature.

For specific details, please refer to commit messages.

Resolves #156
Resolves #155

@maciejSamerdak maciejSamerdak added the bug Something isn't working label Apr 26, 2019
@maciejSamerdak maciejSamerdak added this to the tag 0.1.2 milestone Apr 26, 2019
@maciejSamerdak maciejSamerdak self-assigned this Apr 26, 2019

def get_success_url(self) -> str:
return reverse("custom-projects-list")
def delete_project(request, pk):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this change is fixing the bug?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, DeleteView requires template to work. It serves as a confirmation page (we implemented this functionality as popup in previous view). With no template provided, the app crashes. With any template provided, a GET request is returned after closing popup in previous view and thus the template is rendered with no deletion being performed (because delete view is still waiting for POST to do that). That's definitely not how it should work at all.

At the time I was supposed to apply the fix ASAP, so it was a lot quicker for me to rewrite it to function rather than tangle with Django's mysterious inner mechanics in it's high-level View classes.

It is doable of course, I'd guess we have to overwrite get method so it calls for deletion and then redirects to desired address.

However, from our personal experience (since I developed entirety of eMunchkin based on generic views on my side and I strongly urged others to do the same) it was a lot more time consuming to figure out how the generic views work to know where exactly we must apply changes in functionality that suit our needs (which granted, was a learning experience at the time), than just writing it from scratch, or at the very least from lower-level abstraction.

Since the DeleteView is designed to suit much more sophisticated function than we require, which is to delete given object upon call and redirect (it literally works like a basic function) I'd strongly encourage to leave it as a function-based view, due to it's simplicity. Remodelling inner workings of complex Django View to suit such simplistic function-like purpose, is a major overkill in my opinion.

I am well aware of benefits regarding the principle of keeping all views in same technology, but I'd argue this is a valid exception. I wouldn't use complex mechanics for simplified actions. I think it's an unnecessary waste of resources, both in time and code.

This is also the exact reason we had to write our own views derived from ApiView rather than using generic views when we were still working on REST framework.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, DeleteView requires template to work.

No, it depends if we want to use both GET and POST. Here we only use POST.

With any template provided, a GET request is returned after closing popup in previous view and thus the template is rendered with no deletion being performed (because delete view is still waiting for POST to do that).

I honestly don't understand this part. Do you mean that the problem is that popup is making GET call or that the view is returning redirect to it? Because both can be changed either in popup itself, or in view - it can return redirect, template, or ajax response.

At the time I was supposed to apply the fix ASAP, so it was a lot quicker for me to rewrite it to function rather than tangle with Django's mysterious inner mechanics in it's high-level View classes.

But it has nothing to do with the bug itself. The bug is about missing jquery-ui script that doesn't allow popup to open. The view is working OK.

it was a lot more time consuming to figure out how the generic views work to know where exactly we must apply changes in functionality that suit our needs

Well, that the part of this project to get you guys familiar with how it works. And you don't actually have to do this, because it is already implemented, so you can just optionally get familiar with how it works.

Remodelling inner workings of complex Django View to suit such simplistic function-like purpose, is a major overkill in my opinion.
I wouldn't use complex mechanics for simplified actions.

They are simple generic views that covers most of the possible use cases with overriding 1-2 methods. Getting familiar with how they work and getting used to use them allows you to cover this cases with few lines of code.

I think it's an unnecessary waste of resources, both in time and code.

Again, this is already done.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't understand this part. Do you mean that the problem is that popup is making GET call or that the view is returning redirect to it? Because both can be changed either in popup itself, or in view - it can return redirect, template, or ajax response.

Currently we are getting there by link in tag. If a request method can be specified I wasn't aware of it (though it does seem obvious). By default, a GET was sent and the app crashed.

But it has nothing to do with the bug itself. The bug is about missing jquery-ui script that doesn't allow popup to open. The view is working OK.

After I made the button work again, the app crashed upon call for deleting. Since those two are tightly related, I figured I could quickly fix this newfound bug in same Pull Request.

But since the only change I applied was moving the scripts to different place in code, I'm certain the DeleteView still wouldn't work, because the way it's called from project_form didn't change.

Well, that the part of this project to get you guys familiar with how it works. And you don't actually have to do this, because it is already implemented, so you can just optionally get familiar with how it works.

If we treat it as a learning experience, sure. I'll be happy to dive into these mechanics and figure them out. I already had a good taste of it during eMunchkin development.
But recently, there is a lot of pressure regarding development, since we're struggling to deliver core functionality by the end of the month. This is why I was eager to pick faster solution that I'm familiar with, no to mention the time constraint at that particular time.

Copy link
Collaborator Author

@maciejSamerdak maciejSamerdak Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of learning, I have a question: If you were to choose between generic view and function-based view in this case I take it you'd go for generic view. May I ask why is that specifically? I'd think that if the view's functionality is simple enough for a single, easily readable function, it'd be a better choice. I'd consider using complex class in such case to be at the very least a waste of memory. After all, when an instance is created, all of those unused features from parent class (like entirety of GET request handling) must be loaded, if I'm thinking correctly, making this view more resource consuming than it would be as a function. I am aware those differences are insignificant with today's tech, but to me it's a good design principle. Especially if function-based implementation was faster to develop. Thus I'm wondering, what are the benefits of deriving such view from generic class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maciejSamerdak @kbeker @Szymiks read this too please.

This is why I was eager to pick faster solution that I'm familiar with, no to mention the time constraint at that particular time.

Sure, that's understandable. If we have situation like this and you are waiting for me you may always merge current state when its working but please add an issue in github so we can remember to come back to this later.

I am aware those differences are insignificant with today's tech, but to me it's a good design principle. Especially if function-based implementation was faster to develop. Thus I'm wondering, what are the benefits of deriving such view from generic class?

About benefits:

  • Once you know how to use particular class it is very simple to create a new subclass of it and replace only the parts that you need. When you write function based view you have to provide full implementation each time. This is especially good for those simple, repeatable views that Django provides as generics. So I can't agree that its faster once you learn it, I think its opposite.
  • When you are subclassing a generic view from popular framework like Django you can be more sure that it is implemented without bugs and well tested. It is always easier to make a bug when you create your own implementation (I don't mean "you", I mean anyone).
  • You can use multiple inheritance. You can create your own generic classes which inherits from Django and does your custom logic and reuse them. You can use mixin classes. Basically you can use all the power of object oriented programming (which I hope we will have chance to use once we move all stuff to Django views).
  • I think they are more readable. In example you can see you have a subclass of TemplateView with custom template as an attribute and you already know everything about what this view does.

After all, when an instance is created, all of those unused features from parent class

Well this was actually a little untypical case that we wanted to use only POST part of this view, regularly you would use it fully. And if you need something in the middle you can always add it by just overriding some already existing method, without a need to modify whole function structure.

Those are just first things that comes to my mind. Off course this subject is probably better described in Django-related literature too. You can search for "class based views vs function based views django" and see different opinions and arguments.

I'd consider using complex class in such case to be at the very least a waste of memory.

Its good that you think about things like this but I would not worry too much about it unless we get to that point. I mean, as you have said, with today's tech its rather unnoticeable in web project with this target usage. I think worse bottlenecks could be number/complexity of SQL queries, size of http response or static files.

{% load crispy_forms_tags %}

{% block content %}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra empty lines are not needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a styling error on my part. I just didn't have any time left to fix that.

<b>{{object.name}}</b> {% trans 'project' %}?
</div>

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be placed in {% block extra_head %} above {% block content %}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After fixing the issues in base.html does this still apply or should it all be moved to the {% block extra_script %}?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

css'es should be in {% block extra_head %} which should be located at the end of <head> in base.html.

</div>

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct solution for this.

The main problem is that {% block extra_script %}{% endblock %} was removed from the base.html template, so it must be added there first, at the bottom, above closing </body> tag. It is placed there because all scripts should be loaded after the rest of the html page is rendered. If they are placed in the head, selectors might apply to things that are not rendered yet. Off course they might be also applied just after the HTML code to which they are related, but it is good practice to have them in single place, not scattered around the page.

Second thing is that <script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script> is missing so please add it to the {% block extra_script %}{% endblock %} in project_form.html template.

Please also move existing scripts from <head> above the {% block extra_script %}{% endblock %} in base.html.

Missing {% block extra_script %}{% endblock %} is also causing datepickers to not work, and I am sure they were working so this block must have been removed accidentally

Copy link
Collaborator Author

@maciejSamerdak maciejSamerdak Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we had {% block extra_script %} at the bottom of the base, the javascript dependent project joining feature crashed on page load making it impossible to use it. Report deletion feature was also disabled due to same error. This was because the scripts on those pages (and I mean the custom .js files themselves) were loaded inside the tag in these views and thus they where crashing, because all of dependencies in base were not yet loaded.

I am familiar with principle of loading the scripts only after the rest of the template is loaded to boost the rendering time. I apologise for resulted mess in 'base.html' due to my interference, but project join feature is essential for employee and this bug was detected on the day of release. We absolutely couldn't have released the app in such state and thus I was required to find another ASAP fix.

If I understand correctly, every single javascript reference in all templates must be moved to corresponding {% block extra_script %} below the rest of the code? I will apply the changes shortly and I'll check if all features work as expected.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apologise for resulted mess in 'base.html' due to my interference

Sure don't worry, this project is too about learning right? :)

If I understand correctly, every single javascript reference in all templates must be moved to corresponding {% block extra_script %} below the rest of the code? I will apply the changes shortly and I'll check if all features work as expected.

Yes, if you want you can refactor existing templates in separate PR. All scripts should be moved to this block, while all css'es into extra_head.

Copy link
Contributor

@rwrzesien rwrzesien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach is not correct, please read my comments and apply.

@maciejSamerdak
Copy link
Collaborator Author

Since these changes seem to cause more harm than good, I guess I should drop these commits and start over with applying fixes to base.html.

The way the script was implemented it would sent a GET request,
resulting in crash due to TemplateDoesNotExist error.

Instead of switching `windows.location.href` value, the script now
submits a form with POST method, which is invisible on display.
@maciejSamerdak maciejSamerdak force-pushed the bugfix-delete-button-doesnt-work-for-project branch from 1a55d18 to 28340fe Compare April 30, 2019 11:12
@Karrp Karrp modified the milestones: tag 0.1.2, tag 0.2.0 Apr 30, 2019
@kbeker kbeker merged commit 28340fe into master May 6, 2019
@kbeker kbeker deleted the bugfix-delete-button-doesnt-work-for-project branch May 6, 2019 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Delete button doesn't work for project In creating new project site its impossible to enter correct date if you don't know date format

4 participants