Django «TypeError: объект 'MultiSelectField' не повторяется» при переопределении вариантов MultiSelectField - PullRequest
1 голос
/ 05 августа 2020

Мне нужно создать модель Django CitiesVisited с MultiSelectField , которая будет содержать все города для данной страны, взятые из файла JSON. Сохраненные объекты должны выглядеть так:

Django просмотр админки городов посещенного объекта

Чтобы для каждой страны (модель «CitiesVisitedCountry») каждый пользователь мог сохранить города, которые он посетил.

Models.py

class CitiesVisitedCountry(models.Model):
    """ Every user can have multiple countries visited. Each instance of this class will save oen country """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    country_name = models.CharField(max_length=50)

    def __str__(self):
        return f"{self.country_name}"

    class Meta:
        """ define nemes to be displayed on admin page """
        verbose_name = "Country visited"
        verbose_name_plural = "Countries visited"


class CitiesVisited(models.Model):
    """ For each country visited, save selection of cities visited """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    country = models.ForeignKey(CitiesVisitedCountry, on_delete=models.CASCADE)
    cities = MultiSelectField(choices=select_cities_options("Austria"), null=True, blank=True)

    def __str__(self):
        return f"visited cities for country {self.country} checkbox"

    class Meta:
        """ define nemes to be displayed on admin page """
        verbose_name_plural = "Cities visited checkbox multiple selections"

Проблема в том, что я вынужден использовать список по умолчанию для заполнения вариантов выбора (например, я использую Австрию), и я не могу переопределить этот список при создании объекта.

select_cities_options ( «Австрия»)

def select_cities_options(country_in):
    """
    country_in = 'United States'
    Returns a list with tuple of cities for country_in. Will be used to populate city by country drop-down menus.
    """
    options_by_country = []
    with open(os.path.join(BASE_DIR, 'user_maps', 'static', 'user_maps', 'cities_by_country.json'), mode='r') as file:
        content = json.load(file)
        for country in content:
            if country == str(country_in):
                for city in content[country]:
                    options_by_country.append((city, city))
    return options_by_country

В моем views.py я пытаюсь создать новый объект CitiesVisited, который использует список городов Италии. Этот список параметров должен заменить сохраненный по умолчанию для Австрии. views.py

country_related_object = CitiesVisitedCountry.objects.filter(
                user=request.user, country_name="United States").first()

existing_visited_cities_object = CitiesVisited(
                    user=request.user, country=country_related_object,
                    cities=MultiSelectField(choices=select_cities_options(visited_country))
                )
print(existing_visited_cities_object.cities.choices)
existing_visited_cities_object.save()

print(existing_visited_cities_object.cities.choices) правильно печатает новые параметры:

[('Abano Terme', 'Abano Terme'), ('Abbadia Lariana', 'Abbadia Lariana'), ('Abbadia San Salvatore', 'Abbadia San Salvatore'), ...

Однако, когда я пытаюсь сохранить объект с помощью existing_visited_cities_object.save() I получите эту ошибку:

Internal Server Error: /places_visited/
Traceback (most recent call last):
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\generic\base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\contrib\auth\mixins.py", line 52, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Users\ventafri\Desktop\Repositories\Personal\Holiday Planner\Holiday_Planner\holiday_planner\user_maps\views.py", line 119, in get
    existing_visited_cities_object.save()
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\base.py", line 746, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\base.py", line 784, in save_base
    force_update, using, update_fields,
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\base.py", line 887, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\base.py", line 926, in _do_insert
    using=using, raw=raw,
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\query.py", line 1204, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\sql\compiler.py", line 1391, in execute_sql
    for sql, params in self.as_sql():
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\sql\compiler.py", line 1336, in as_sql
    for obj in self.query.objs
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\sql\compiler.py", line 1336, in <listcomp>
    for obj in self.query.objs
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\sql\compiler.py", line 1335, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\sql\compiler.py", line 1276, in prepare_value
    value = field.get_db_prep_save(value, connection=self.connection)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\django\db\models\fields\__init__.py", line 821, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\multiselectfield\db\fields.py", line 145, in get_db_prep_value
    value = self.get_prep_value(value)
  File "C:\Users\ventafri\AppData\Local\Programs\Python\Python36\lib\site-packages\multiselectfield\db\fields.py", line 141, in get_prep_value
    return '' if value is None else ",".join(map(str, value))
TypeError: 'MultiSelectField' object is not iterable

Как правильно сохранить новый объект CitiesVisited, чтобы он правильно отображал новый правильный список городов для страны, на которую он ссылается?

Спасибо

...