Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Nested and Reverse relationship don't cloned #488

Closed
2 tasks done
ma1onso opened this issue Sep 16, 2021 · 7 comments · Fixed by #493
Closed
2 tasks done

[BUG] Nested and Reverse relationship don't cloned #488

ma1onso opened this issue Sep 16, 2021 · 7 comments · Fixed by #493
Labels
bug Something isn't working

Comments

@ma1onso
Copy link

ma1onso commented Sep 16, 2021

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug?

I have the next models:

class Indication(CloneMixin, TimeStampedModel):
    ....
    _clone_m2o_or_o2m_fields = ['cases']

class Case(CloneMixin, TimeStampedModel):
    indication = models.ForeignKey(
        'presentations.Indication', on_delete=models.CASCADE, related_name='cases',
    )
    _clone_m2o_or_o2m_fields = ['slides']

class Slide(CloneMixin, TimeStampedModel):
    case = models.ForeignKey(
        'presentations.Case', on_delete=models.CASCADE, related_name='slides',
    )
    survey = models.OneToOneField(
        'surveys.Survey', on_delete=models.SET_NULL, null=True, blank=True,
    )
    
    _clone_o2o_fields = ['survey']

class Survey(CloneMixin, TimeStampedModel, LanguageModelWithDefaultMixin):
	name = models.CharField(
		_('Name'), max_length=400
	)
	description = models.TextField(
		_('Description')
	)
	type = models.CharField(
		choices=surveys_choices.SURVEY_TYPES, max_length=15, default=surveys_choices.SURVEY_GENERAL_TYPE,
	)
	is_published = models.BooleanField(
		_('Users can see it and answer it'), default=True,
	)
	show_all_questions = models.BooleanField(
		_('Show matrix questions expanded'), default=False,
	)
	chart_type = models.CharField(
		max_length=30, choices=presentations_choices.CHART_TYPES, null=True, blank=True,
		help_text=_('Only use if needed draw a specific chart type')
	)

	_clone_m2o_or_o2m_fields = ['questions', ]

	objects = SurveyManager()

	class Meta:
		verbose_name = _('survey')
		verbose_name_plural = _('surveys')

	def __str__(self):
		return self.name

class Question(CloneMixin, TimeStampedModel):
	text = models.TextField(
		_('Text')
	)
	reminder_text = models.TextField(
		null=True, blank=True,
	)
	first_number = models.PositiveSmallIntegerField(
		null=True, blank=True, help_text=_('First number for range numeric questions')
	)
	last_number = models.PositiveSmallIntegerField(
		null=True, blank=True, help_text=_('Last number for range numeric questions')
	)
	order = models.PositiveSmallIntegerField(
		_('Order'), help_text=_('Order for show questions to user')
	)
	type = models.CharField(
		_('Type'), max_length=200, choices=surveys_choices.QUESTION_TYPES, default=surveys_choices.QUESTION_SELECT
	)
	unique_group_text = models.CharField(
		max_length=500,
		help_text=_(
			'This text change in each Question that is part of a group. Used to display the proper label at the charts'
		),
		blank=True,
	)
	indication_type = models.CharField(
		max_length=30, choices=presentations_choices.INDICATION_TYPE, null=True, blank=True,
		help_text=_(
			'Questions using this field belong to demographic surveys, and only will be show when the event has '
			'indication with type equal to questions with the same type'
		)
	)
	is_with_hide_chart = models.BooleanField(
		default=False,
	)
	chart_type = models.CharField(
		max_length=30, choices=presentations_choices.CHART_TYPES, null=True, blank=True,
		help_text=_('Only use if needed draw a specific chart type')
	)
	is_with_random_choices = models.BooleanField(
		default=False, help_text=_('The choices always are random'),
	)
	# Relationships
	conditional_choices = models.ManyToManyField(
		'surveys.QuestionChoice', blank=True,
		help_text=_('If the user select the question into the QuestionChoice, then jump to current question'),
		related_name='questions',
	)
	survey = models.ForeignKey(
		'surveys.Survey', on_delete=models.CASCADE, verbose_name=_('Survey'), related_name='questions',
	)
	question_group = models.ForeignKey(
		'surveys.QuestionGroup', on_delete=models.SET_NULL, null=True, blank=True, related_name='questions',
	)

	_clone_m2m_fields = ['conditional_choices']
	_clone_m2o_or_o2m_fields = ['choices']
	# _clone_m2o_or_o2m_fields = ['choices', 'question_group']

	class Meta:
		verbose_name = _('question')
		verbose_name_plural = _('questions')
		ordering = ('survey', 'order')

	def __str__(self):
		return f'ID: {self.id} / Survey: {self.survey.name}'

class QuestionChoice(CloneMixin, TimeStampedModel):
	question = models.ForeignKey(
		'surveys.Question', on_delete=models.CASCADE, verbose_name=_('Question'), related_name='choices'
	)

I cloned almost all without problem, but, the questions from reverse relationship between Question and Survey, don't clone.

To Reproduce

  1. Configure the admin model to clone:
class CaseInline(admin.TabularInline):
	model = presentations_models.Case
	show_change_link = True
	extra = 1


class IndicationAdmin(CloneModelAdmin):
	list_display = ('id', 'title', 'language')
	inlines = [
		CaseInline,
	]

admin.site.register(presentations_models.Indication, IndicationAdmin)
  1. Clone from django admin
    Screenshot from 2021-09-16 15-02-57

Note:
Survey and Question admin are declared so:

class QuestionInline(admin.TabularInline):
	model = surveys_models.Question
	show_change_link = True
	raw_id_fields = ['conditional_choices', ]
	extra = 1

class SurveyAdmin(CloneModelAdmin):
	save_as = True
	inlines = [
		QuestionInline,
	]

admin.site.register(surveys_models.Survey, SurveyAdmin)

class QuestionChoiceInline(admin.TabularInline):
	model = surveys_models.QuestionChoice
	show_change_link = True
	extra = 1


class QuestionAdmin(admin.ModelAdmin):
	list_display = ('id', 'text', 'survey', 'type', 'question_group',)
	search_fields = ('text', 'unique_group_text',)
	list_filter = ('survey__language', 'type', )
	raw_id_fields = ['conditional_choices']
	inlines = [
		QuestionChoiceInline,
	]


admin.site.register(surveys_models.Question, QuestionAdmin)

What OS are you seeing the problem on?

linux

Expected behavior?

Clone all data, included the questions from a Survey

Relevant log output

No response

Anything else?

django 3.1.13
django-clone 2.9.4
python 3.7

Code of Conduct

  • I agree to follow this project's Code of Conduct
@ma1onso ma1onso added the bug Something isn't working label Sep 16, 2021
@github-actions
Copy link
Contributor

Thanks for reporting this issue.

@jackton1
Copy link
Member

jackton1 commented Sep 17, 2021

Hi @ma1onso Can you also include the version of django and django clone your experiencing the issue.

@ma1onso
Copy link
Author

ma1onso commented Sep 17, 2021

Hi @ma1onso Can you also include the version of django and django clone your experiencing the issue.

django 3.1.13
django-clone 2.9.4
python 3.7

@jackton1
Copy link
Member

jackton1 commented Sep 18, 2021

@ma1onso Can you also clarify which admin and what code is used in cloning the Survey objects

This is missing the QuestionInline I’ll suggest just including the Survey and Question models with their related admin views this would be helpful in providing any feedback.

class SurveyAdmin(CloneModelAdmin):
	save_as = True
	inlines = [
		QuestionInline,
	]

@ma1onso
Copy link
Author

ma1onso commented Sep 20, 2021

@ma1onso Can you also clarify which admin and what code is used in cloning the Survey objects

This is missing the QuestionInline I’ll suggest just including the Survey and Question models with their related admin views this would be helpful in providing any feedback.

class SurveyAdmin(CloneModelAdmin):
	save_as = True
	inlines = [
		QuestionInline,
	]

Hi @jackton1, I put more information in the description above, I'm using the default Django admin interface.

Thanks :)

@jackton1
Copy link
Member

Perfect, I'll try to replicate the issue later today.

@jcctudela
Copy link

The point is that the o2o clone, is not calling to the make_clone of the object, but just to the _create_copy_of_instance

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 a pull request may close this issue.

3 participants